目的是什么:belongs_to关联的条件?

时间:2010-01-28 17:26:53

标签: ruby-on-rails activerecord

说我与附加条件有以下关联:

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.

belongs_to上的:conditions选项的API doc states将:

  

指定条件   关联对象必须按顺序相遇   要包含在WHERE SQL中   片段,例如authorized = 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并保存了它。关联将持久保存到db(请参阅上面最后一行中的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>

对我来说似乎很奇怪,但你去了。

1 个答案:

答案 0 :(得分: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之外的任何其他内容。 / p>