Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Returning Block on Association Extension Causes Proxy Owner To Load Target

#821

If this were a bug that could be fixed I'd take a stab at the tests, but I pretty much doubt that it is. So this ticket is more of a warning to others. I have found that using a returning block inside of an association extension causes the proxy owner to load the target. I came across this bug in 1.2.6 and see that the same results happen in 2.1. Here is some code that demonstrates the issue.

Because our production app uses a good deal of association extensions and there is a lot of data, this started to really affect performance. If any things this can be accounted for either in the implementation of returning and/or the association proxy classes, please let me know and I can take a stab at a test.



class User < ActiveRecord::Base
  has_many  :articles, :extend => FooBarReturning
end

module FooBarReturning

  def foo
    c = build
    # DOES NOT CAUSE SELECT ALL AS NORMAL
  end

  def bar
    returning c = build do
      # SELECT * FROM "articles" WHERE ("columns".user_id = 1)
    end
  end

  def returning
    returning build do |c|
      # SELECT * FROM "articles" WHERE ("columns".user_id = 1)
    end
  end

end


class User < ActiveRecord::Base

  has_many  :articles do
    def foo_bar_returning
      returning c = build do
        # SELECT * FROM "articles" WHERE ("columns".user_id = 1)
      end
    end
  end

end

Reported by Ken Collins · August 13th, 2008 @ 06:30 PM

State: wontfix
Milestone: 2.x
Assigned to: nobody
Importance: none

Activity

  1. Ken Collins
    Ken Collins

    I forgot to mention that if you used the returning block inside of a controller (just anywhere outside of an association extension) that the SQL is just fine. The issue only seems to be when using the returning block in an association extensions.

    ALSO, I have a type above... my example association method that shows that either use of returning should have been as follows.

    
    module FooBarReturning
    
      def foo_bar_returning
        returning build do |c|
          # SELECT * FROM "articles" WHERE ("columns".user_id = 1)
        end
      end
    
    end
    

    August 13th, 2008 @ 06:35 PM

  2. Frederick Cheung
    Frederick Cheung

    returning is a method activesupport adds to Object, so it's available everywhere. Except on an association proxy, because association proxies undef all their methods (so that they filter through to the target), including returning.

    With returning you don't care who you call returning on though, so something like

    
    Object.returning build do |c|
    ...
    end
    

    Seing as returning doesn't depending on who its called on (it's just injected everywhere for convenience), arguably you could just not undef it.

    August 13th, 2008 @ 09:09 PM

  3. Ken Collins
    Ken Collins

    Not sure what you are saying... returning works in the association extension but it just has ILL EFFECTS of loading the target. I am pretty sure Object.returning does the same.

    August 13th, 2008 @ 09:15 PM

  4. Frederick Cheung
    Frederick Cheung

    because returning is undeffed on the proxy, it has to load the array in order to call it. By calling it on Object you avoid that (the choice of Object is arbitrary). try it.

    August 13th, 2008 @ 09:18 PM

  5. Ken Collins
  6. josh
    josh
    • State changed from new to wontfix

    November 22nd, 2008 @ 07:25 PM