Thanks.

(the find_each I referenced in my question is (basically) the same as 
find_in_batches)

The question is really why:

order.line_items != LineItem.where(:order_id => order.id)

So, I think what you're saying is that
order.line_items returns an array, not a relation.


On Tuesday, June 5, 2012 7:02:25 PM UTC-7, Ruby-Forum.com User wrote:
>
> John H. wrote in post #1063205: 
> > I'm a bit unclear what's going on with relations. I'm hoping someone can 
> > help explain it to me. 
> > 
> > Lets say we have a model with orders and line_items such that an order 
> > has 
> > many line_items. Thus: 
> > 
> > class Order 
> >   has_may :line_items 
> > end 
> > class LineItem 
> >   belongs_to :order 
> > end 
> > 
> > When I have an order and call line_items what's going on?  e.g. 
> > 
> > Order order = Order.first 
> > order.line_items.each {|li| puts li } 
> > 
> > I thought that was basically an alias for: 
> > 
> > Order order = Order.first 
> > LineItem.where(:order_id => order.id).each {|li| puts li } 
>
> This is an over-simplification. Let me illustrate by example: 
>
> 1.9.3p194 :010 > order = Order.first 
>   Order Load (0.3ms)  SELECT "orders".* FROM "orders" LIMIT 1 
>  => #<Order id: 1, name: "First item", description: "First one", price: 
> nil, created_at: "2012-06-06 01:20:03", updated_at: "2012-06-06 
> 01:20:03"> 
>
> Notice first that selecting the order does not touch the line_items 
> table at all. At this point the order.line_items method is represented 
> by an ActiveRecord::Relation object. Accessing this relation object will 
> load (fire) the relation and populate the array. 
>
> Now let's take look at the line_items: 
>
> 1.9.3p194 :002 > order.line_items 
>   LineItem Load (0.2ms)  SELECT "line_items".* FROM "line_items" WHERE 
> "line_items"."order_id" = 1 
>  => [#<LineItem id: 1, order_id: 1, name: "Line 1", quantity: 5, 
> created_at: "2012-06-06 01:21:24", updated_at: "2012-06-06 01:21:24">] 
> 1.9.3p194 :003 > order.line_items 
>  => [#<LineItem id: 1, order_id: 1, name: "Line 1", quantity: 5, 
> created_at: "2012-06-06 01:21:24", updated_at: "2012-06-06 01:21:24">] 
>
> Notice the first time we access line_items ActiveRecord will load the 
> association by running a generated SQL statement. Subsequent calls do 
> not reissue the SQL statement. 
>
> Let's take a look at what is reported as the class for order.line_items: 
>
> 1.9.3p194 :003 > puts order.line_items.class 
> Array 
>
> This appears to be a typical Array object, but it's really more 
> complicated than that. What you're seeing is not a simple Array object, 
> but rather an Array that has been extended with some Rails magic. Let's 
> take a look that the ancestry of that resulting "Array" object: 
>
> 1.9.3p194 :004 > puts order.line_items.class.ancestors 
> Array 
> JSON::Ext::Generator::GeneratorMethods::Array 
> Enumerable 
> Object 
> PP::ObjectMixin 
> JSON::Ext::Generator::GeneratorMethods::Object 
> ActiveSupport::Dependencies::Loadable 
> Kernel 
> BasicObject 
>
> Here's the ancestry of a plain old Ruby Array: 
>
> # Ruby (No Rails) 
> $ irb 
> 1.9.3p194 :001 > Array.ancestors 
>  => [Array, Enumerable, Object, Kernel, BasicObject] 
>
> In fact all Array objects in rails have the additional magic added to 
> them: 
>
> # Ruby on Rails 
> $ rails console 
> Loading development environment (Rails 3.2.3) 
> 1.9.3p194 :001 > puts Array.ancestors 
> Array 
> JSON::Ext::Generator::GeneratorMethods::Array 
> Enumerable 
> Object 
> PP::ObjectMixin 
> JSON::Ext::Generator::GeneratorMethods::Object 
> ActiveSupport::Dependencies::Loadable 
> Kernel 
> BasicObject 
>
> > but, this isn't consistent with batching. 
> > 
> > So if we do 
> > 
> > Order order = Order.first 
> > 
> > # this doesn't appear to work, it's not batching, just finding all of 
> > the 
> > line items and iterating 
> > order.line_items.find_each {|li| puts li } 
>
> Hopefully what I explained above will clear up what's happening here. 
> That very first access of order.line_items is causing that relation 
> object to fire and load the objects. 
>
> What you probably want is the find_in_batches method provided by 
> ActiveRecord: 
>
>
> http://api.rubyonrails.org/classes/ActiveRecord/Batches.html#method-i-find_in_batches
>  
>
> -- 
> Posted via http://www.ruby-forum.com/. 
>

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/rubyonrails-talk/-/Q2azabP6S_kJ.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to 
rubyonrails-talk+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to