条件对一个belongs_to的关联关系:的目的是什么? [英] What is the purpose of :conditions on a belongs_to association?

查看:163
本文介绍了条件对一个belongs_to的关联关系:的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个附加条件如下关联关系:

  belongs_to的:管理员用户名,
    :将class_name => '用户',
    :foreign_key => :admin_user_id,
    :条件=> users.admin = TRUE'#或散列或数组,{任何变化:管理=>真正的}等。
 

借助 API文档的状态中的:条件选项上belongs_to的将:

  

指定条件的   关联对象必须满足   被列为一个WHERE SQL   片段,如授权= 1

但输出显示没有WHERE子句的选择,并且在任何情况下,我会期望在一个belongs_to的这样的条件将prevent坚持这种关系,首先,在INSERT而不是SELECT。此选项似乎有一个belongs_to的关联没有任何影响,除非我失去了一些东西。该选项可使一个的has_many感,我只是不明白如何应用于belongs_to的。

编辑:进一步的研究表明,你确实可以持续违反条件的关联,但你无法检索相关记录的的记录将被重新装入

在像这样定义一个类:

 类窗口小部件<的ActiveRecord :: Base的

    belongs_to的:big_bloop,
        :将class_name => BLOOP
        :foreign_key => :big_bloop_id,
        :条件=> [big_bloop =?,真]

    belongs_to的:BLOOP,:条件=> [big_bloop =?,真]

结束
 

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

 >> BLOOP = Bloop.new
=> #< BLOOP ID:无,名:无,big_bloop:无>
>>小工具= Widget.new
=> #<小部件ID:无,名:无,bloop_id:无,big_bloop_id:无>
>> widget.bloop = BLOOP
=> #< BLOOP ID:无,名:无,big_bloop:无>
>> widget.save!
=>真正
>>小工具
=> #<小部件ID:2,名称:无,bloop_id:2,big_bloop_id:无>
 

我相关的BLOOP违反的情况,并保存它。该协会坚持以分贝(见bloop_id和big_bloop_id上面的最后一行)。

 >> big_bloop = Bloop.new
=> #< BLOOP ID:无,名:无,big_bloop:无>
>> widget.big_bloop = big_bloop
=> #< BLOOP ID:无,名:无,big_bloop:无>
>> widget.save!
=>真正
>>小工具
=> #<小部件ID:2,名称:无,bloop_id:2,big_bloop_id:3>
 

同样的事情,不同的属性。

 >> widget.bloop
=> #< BLOOP ID:2,名称:无,big_bloop:无>
>> widget.big_bloop
=> #< BLOOP ID:3名:无,big_bloop:无>
 

这两种无效bloops保留在内存中。

 >> widget.reload
=> #<小部件ID:2,名称:无,bloop_id:2,big_bloop_id:3>
>> widget.bloop
=>零
>> widget.big_bloop
=>零
 

重装后,他们走了,因为在SELECT语句确实使用WHERE子句将它们排除在外。

  BLOOP负荷(0.3ms)SELECT * FROM`bloops` WHERE(`bloops`.`id` = 2 AND(big_bloop = 1))
 

然而小部件仍具有参考:

 >>小工具
=> #<小部件ID:2,名称:无,bloop_id:2,big_bloop_id:3>
 

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

解决方案

这是一个不错的发现!

我首先想到的是,这可能只是AssociationProxy基类或类似的一些通用的东西。但进一步挖下来,似乎存在的特定选项belongs_to的许可证的列表:

  @@ valid_keys_for_belongs_to_association = [
  :将class_name,:primary_key,:foreign_key,:foreign_type,:远程:选择,:条件,
  :包括:依赖,:counter_cache,:延长,多态,:只读,
  :验证,:触摸
]
 

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

我不知道你怎么测试的WHERE,虽然。我的测试清楚地显示出它的确实包含在WHERE子句:

 类的东西<的ActiveRecord :: Base的;结束

一流的窗口小部件<的ActiveRecord :: Base的
  belongs_to的:首先,:条件=> ['名称=?','Jigglymabob']
结束

Thing.create:名称=> Jigglymabob
#=> #<东西ID:1,名称:Jigglymabob>
W = Widget.create:名称=> Wookeleywoo',:thing_id => 1
#=> #<小部件ID:1,名称:Wookeleywoo,thing_id:1>
w.thing
#=> #<东西ID:1,名称:Jigglymabob>
 

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

 创建的事情(0.3ms)INSERT INTO的东西(名)VALUES('Jigglymabob)
控件创建(0.3ms)INSERT INTO小工具(名,thing_id)VALUES('Wookeleywoo',1)
事情负载(0.6ms)SELECT * FROM东西WHERE(物。ID= 1 AND(NAME ='Jigglymabob'))
 

由于我想和打字了你,我才意识到我还没有给出真正的回答你的问题。 :)我能想到的只有一个理由,这ActiveRecord的,那是因为它是没有额外的麻烦来实现,而且也没有好处留出来。

有人在那里可能正与一个旧的数据库,其中在办公室和mdash的金科玉律一个奇怪的边缘情况,即每个人都学会了艰辛的道路&mdash;就是永远不会有一个Wookeleywoo部件连接以外的任何一个Jigglymabob <。 / P>

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 API doc states that the :conditions option on belongs_to will:

Specify the conditions that the associated object must meet in order to be included as a WHERE SQL fragment, such as authorized = 1.

But the output shows no WHERE clause on the select, and in any case I would expect that conditions like this on a belongs_to would prevent persisting that relationship to begin with, on the INSERT not the SELECT. This option seems to have no effect on a belongs_to association, unless I'm missing something. The option makes sense on a has_many, I just don't see how it applies to belongs_to.

EDIT: Further research reveals that you can indeed persist an association that violates a condition, but you cannot retrieve the associated record after the record is reloaded.

On a class defined like so:

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've associated a bloop that violates the condition and saved it. The association is persisted to the db (see bloop_id and big_bloop_id on 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 reload, they're gone, because the SELECT statement does indeed use a WHERE clause to exclude them.

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

And yet the widget still has the references:

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

Seems odd to me, but there you go.

解决方案

That's a nice find!

My first thought was that this might just be some generic thing of the AssociationProxy base class or the like. But digging further down, there appears to be a list of specific options belongs_to permits:

@@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, the possibly subconscious decision was made to put that there. :)

I'm not sure how you tested the WHERE, though. My testing clearly shows it does include the 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 all this, my logfile 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'm trying and typing this out for you, I realized I still haven't given a real answer to your question. :) I can think of only one reason to have this in ActiveRecord, and that's because it was no extra hassle to implement, and there's no benefit to leaving it out.

Someone out there may be working on a strange edge case with a legacy database, where the golden rule in the office—that everyone learns the hard way—is to never have a Wookeleywoo widget attached to anything other than a Jigglymabob.

这篇关于条件对一个belongs_to的关联关系:的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆