2010-01-28 41 views
7

说我有具有附接的状态下的关联:有什么用途:belongs_to关联的条件是什么?

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. 

API doc states使得:上belongs_to的条件选项:

指定该 相关联的对象必须按顺序 符合条件被包括为WHERE SQL 片段,例如授权= 1。

但是输出在select上没有显示WHERE子句,并且在任何情况下我都希望在belongs_to上这样的条件会阻止以INSERT而不是SELECT开头的关系开始。这个选项似乎对belongs_to关联没有影响,除非我遗漏了一些东西。该选项在has_many上有意义,我只是看不出它适用于belongs_to。

编辑:进一步的研究显示,你确实可以坚持一个违反条件的关联,但你不能在之后检索关联记录记录被重新加载。

像这样定义一个类:

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 

...从我们看到控制台:

>> 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> 

我有关违反条件并保存它BLOOP。该关联被持久化到数据库(参见上面最后一行的bloop_id和big_bloop_id)。

>> 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> 

相同的东西,不同的属性。

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

这两个无效的bloops都保留在内存中。

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

重新加载后,它们消失了,因为SELECT语句确实使用WHERE子句排除它们。

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

然而小部件仍具有参考:

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

似乎很奇怪我,但你去那里。

回答

4

这是一个很好的发现!

我首先想到的是,这可能只是AssociationProxy基类或类似的一些通用的东西。但挖进一步下跌,似乎有特定的选项列表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 
] 

因此,在某些时候,可能潜意识作出决定,把存在。 :)

我不知道你怎么测试的WHERE,虽然。我的测试清楚地表明它确实包括在WHERE子句:

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"> 

这一切后,我的日志文件中包含:

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')) 

正如我试图和打字了你,我才意识到我仍然没有真正回答你的问题。 :)我只能想到在ActiveRecord中有这样的一个理由,那是因为它没有额外的实施麻烦,而且没有任何好处。

有人在那里可以工作在一个奇怪的边缘情况与传统数据库中,在办公室—是每个人都学会了艰辛的道路—的黄金法则是永远不会有一个Wookeleywoo部件连接到除Jigglymabob其他任何东西。

+0

谢谢你,非常有帮助。 – 2010-01-28 20:15:04