Rails: Why can't you set an association to nil in a where clause? Rails: Why can't you set an association to nil in a where clause? ruby-on-rails ruby-on-rails

Rails: Why can't you set an association to nil in a where clause?


when you use pass in the conditions into ActiveRecord, it actually tries to analyze the objects that you passed in, is it a string? an array? a hash? and what's in the string, array or hash?

and in your case, a hash, so it's trying to analyze what's in the hash, in the first statement (which works), you passed in a model instance as the value, so it tries to find if there are any associations that mapped to the key your specified and voila, it found it and everything works as planned

in the second case, you passed in nil as the value, now, ActiveRecord sees that it's a nil object, so it decided that it's not an association. note that it doesn't look at the key, but it only looked at the value, thus it tries to find if there's any column that mapped to the key, but it couldn't find, returning an error

in the last case, you passed in nil as the value, same thing, it tried to find a column which mapped to :collection_id, thus it passed in nil as the value in the SQL statement, and it returned successfully

so it's just an unfortunate considerations taken by ActiveRecord that makes the second case not working =)

hope this clarifies! =D


My guess is that it's like the famous rails .find vs .find_by_id.

.find is designed to throw an exception if it cannot find any association.

where as .find_by_id will just return nil if doesn't find any association.

so in your .where statement, when you search for the collection it's probably treating that like a .find and when you search by collection_id it will return nil just like .find_by_id does if it can't find any associated collection.

I'm not sure how these two methods differ in Activerecord's inner workings, but they are designed to react differently to nil results.


I think your answer is in ActiveRecord::PredicateBuilder.build_from_hash. There is a case statement in there that checks the class of each value in the hash, and it specifically looks for ActiveRecord::Relation