【问题标题】:What is the purpose of :conditions on a belongs_to association?:belongs_to 关联的条件的目的是什么?
【发布时间】:2011-01-10 12:30:29
【问题描述】:

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

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 并保存了它。关联被持久化到数据库(参见上面最后一行的 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>

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

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

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

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    这是一个不错的发现!

    我的第一个想法是,这可能只是 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 以外的任何东西。

    【讨论】:

      猜你喜欢
      • 2016-02-23
      • 2011-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-04
      相关资源
      最近更新 更多