Rails 3.1, has_many relationship and new records problem

222 views
Skip to first unread message

Daro

unread,
Sep 22, 2011, 10:12:48 AM9/22/11
to Ruby on Rails: Core
Supose I have a simple has_many relationship betwen model_1 and
model_2:

class Model1 < ActiveRecord::Base
has_many :models_2
end

class Model2 < ActiveRecord::Base
belongs_to :model_1
end

Now, I create an instance of Model2 through the relationship:

irb>m1 = Model1.first
irb>m2 = m1.models_2.new

Now, if I want to ask for the size of the relationship, there's a huge
difference between Rails 3.0.x and Rails 3.1.

Following the previous example, in Rails 3.0.x i get:

irb>m1.models_2.any?
irb>false
irb>m1.models_2.size
irb>0

This means, new objects are not being considered

This exact same query in Rails 3.1:

irb>m1.models_2.any?
irb>true #OMG!!
irb>m1.models_2.size
irb>1
So, the solution is:

irb>m1.models_2.all.any?
irb>false
irb>m1.models_2.all.size
irb>0

If I have to change ALL my relationships with .all, I'm in a big
trouble... am I missing something?
Thank you very much.

Nicolás Sanguinetti

unread,
Sep 22, 2011, 2:07:12 PM9/22/11
to rubyonra...@googlegroups.com

Looking a thttps://github.com/rails/rails/blob/v3.1.0/activerecord/lib/active_record/relation.rb#L141-143
(and the same in v3.0.10, for example) I can't figure out why that
isn't the same, since the code is pretty much the same, so I'm
probably missing something.

That said, you have 3 ways of querying the size of an ActiveRecord relation:

* #length will load all the objects into an array (unless they are
already loaded) and then return the array's size.
* #count will force a DB count and return that result, without loading
the model instances into memory.
* #size will, if the objects are already loaded in an array, return
the #length, or otherwise call #count.

So you don't need to force an "all", that will load your objects in
memory. Just calling #count should do.

Cheers,
-foca

> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To unsubscribe from this group, send email to rubyonrails-co...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
>
>

Everton Moreth

unread,
Sep 24, 2011, 7:43:17 PM9/24/11
to rubyonra...@googlegroups.com
I believe that this is a rails 3.0 bug.

In both 3.0 and 3.1 ActiveRecord::Relation's #build is an alias for #new. But somehow, in rails 3.0 this behaviour is not the same, #build will increase the "size counter" and #new will not.

This was probably fixed in rails 3.1.

Everton Moreth



2011/9/22 Nicolás Sanguinetti <h...@nicolassanguinetti.info>

Mark Lee

unread,
Sep 27, 2011, 4:31:21 AM9/27/11
to rubyonra...@googlegroups.com
This is a real problem, waiting for news

Jon Leighton

unread,
Sep 28, 2011, 1:37:41 PM9/28/11
to rubyonra...@googlegroups.com
On Thu, 2011-09-22 at 07:12 -0700, Daro wrote:
> If I have to change ALL my relationships with .all, I'm in a big
> trouble... am I missing something?
> Thank you very much.

I can confirm what you have described: https://gist.github.com/1248588

In 3.0 there were inconsistencies between calling 'new' and 'build' on
an association. I consider this a bug. In 3.1 the inconsistencies are
tidied up, resulting in the behaviour you describe.

If you want to issue a COUNT query to the db, use #count rather than
#size.

Cheers

--
http://jonathanleighton.com/

signature.asc
Reply all
Reply to author
Forward
0 new messages