What is the purpose: conditions for membership in an association?

Let's say I have the following association with an attached condition:

belongs_to :admin_user, :class_name => 'User', :foreign_key => :admin_user_id, :conditions=> 'users.admin=TRUE' # or any variation with hash or array, {:admin => true}, etc. 

The doc API states that the: conditions parameter on the __to property will be:

Indicate the conditions under which the related object must match the order of being included as a WHERE SQL fragment, such as resolved = 1.

But the output does not display the WHERE clause on select, and in any case, I would expect conditions like this on the assign_to function to prevent this relationship from starting, starting with INSERT, not SELECT. This parameter does not seem to affect the belongs_to association, unless I see something. The option makes sense on has_many, I just don’t see how this relates to belongs_to.

EDIT: Further research shows that you can really maintain a connection that violates the condition, but you cannot get a related record after reloading the record.

In a class defined like this:

 class Widget < ActiveRecord::Base belongs_to :big_bloop, :class_name => "Bloop", :foreign_key => :big_bloop_id, :conditions => ["big_bloop = ?", true] belongs_to :bloop, :conditions => ["big_bloop = ?", true] end 

... from the console we see:

 >> bloop = Bloop.new => #<Bloop id: nil, name: nil, big_bloop: nil> >> widget = Widget.new => #<Widget id: nil, name: nil, bloop_id: nil, big_bloop_id: nil> >> widget.bloop = bloop => #<Bloop id: nil, name: nil, big_bloop: nil> >> widget.save! => true >> widget => #<Widget id: 2, name: nil, bloop_id: 2, big_bloop_id: nil> 

I tied a bloop that violated the condition and saved it. The connection is saved in db (see Bloop_id and big_bloop_id in the last line above).

 >> big_bloop = Bloop.new => #<Bloop id: nil, name: nil, big_bloop: nil> >> widget.big_bloop = big_bloop => #<Bloop id: nil, name: nil, big_bloop: nil> >> widget.save! => true >> widget => #<Widget id: 2, name: nil, bloop_id: 2, big_bloop_id: 3> 

Same thing, different attribute.

 >> widget.bloop => #<Bloop id: 2, name: nil, big_bloop: nil> >> widget.big_bloop => #<Bloop id: 3, name: nil, big_bloop: nil> 

Both invalid bloops remain in memory.

 >> widget.reload => #<Widget id: 2, name: nil, bloop_id: 2, big_bloop_id: 3> >> widget.bloop => nil >> widget.big_bloop => nil 

After the reboot, they disappeared because the SELECT statement really uses the WHERE clause to exclude them.

 Bloop Load (0.3ms) SELECT * FROM `bloops` WHERE (`bloops`.`id` = 2 AND (big_bloop = 1)) 

And still the widget still has links:

 >> widget => #<Widget id: 2, name: nil, bloop_id: 2, big_bloop_id: 3> 

Seems strange to me, but there you go.

+7
ruby-on-rails activerecord
source share
1 answer

This is a good find!

My first thought was that it could be just a general element of the AssociationProxy base class or the like. But digging further, a list of certain options appears that belongs to:

 @@valid_keys_for_belongs_to_association = [ :class_name, :primary_key, :foreign_key, :foreign_type, :remote, :select, :conditions, :include, :dependent, :counter_cache, :extend, :polymorphic, :readonly, :validate, :touch ] 

So, at some point, it may have been a subconscious decision to put this on. :)

I'm not sure how you tested WHERE. My testing clearly shows that includes a WHERE clause:

 class Thing < ActiveRecord::Base; end class Widget < ActiveRecord::Base belongs_to :thing, :conditions => ['name = ?', 'Jigglymabob'] end Thing.create :name => 'Jigglymabob' # => #<Thing id: 1, name: "Jigglymabob"> w = Widget.create :name => 'Wookeleywoo', :thing_id => 1 # => #<Widget id: 1, name: "Wookeleywoo", thing_id: 1> w.thing # => #<Thing id: 1, name: "Jigglymabob"> 

After that, my log file contains:

 Thing Create (0.3ms) INSERT INTO "things" ("name") VALUES('Jigglymabob') Widget Create (0.3ms) INSERT INTO "widgets" ("name", "thing_id") VALUES('Wookeleywoo', 1) Thing Load (0.6ms) SELECT * FROM "things" WHERE ("things"."id" = 1 AND (name = 'Jigglymabob')) 

As I try and type this for you, I realized that I still have not answered your question. :) I can only think of one reason to have this in ActiveRecord, and this is because there was no unnecessary hassle to implement, and there is no benefit to leave it.

Someone might be working on a weird edge case with an outdated database where the golden rule in the office is that everyone learns the hard way to never have a Wookeleywoo widget tied to anything other than Jigglymabob.

+4
source share

All Articles