rails has_many setter应该设置条件,如果指定的话

时间:2011-04-26 04:27:30

标签: ruby-on-rails ruby-on-rails-3 activerecord associations

这对我来说似乎是Rails中的一个错误,但我可能做的不多。那么我怎样才能达到预期的行为呢?

假设我们有:

class User < ActiveRecord::Base
  has_many :awesome_friends, :class_name => "Friend", :conditions => {:awesome => true}
end

执行代码:

>> my_user.awesome_friends << Friend.new(:name=>'jim')

之后,当我检查这个朋友对象时,我看到填充了user_id字段。但我也希望看到“真棒”这个“真棒”列,但事实并非如此。

此外,如果我从控制台执行以下操作:

>> my_user.awesome_friends << Friend.new(:name=>'jim')
>> my_user.awesome_friends
= [#<Friend id:1, name:"jim", awesome:nil>]
# Quit and restart the console
>> my_user.awesome_friends
= []

对此有何想法?我认为条件哈希可能是任意复杂的,使得集成到setter中是不可能的。但从某种意义上说,默认情况下我们传递的条件是“:user_id =&gt; self.id”,并且设置已经设置,其他人不应该这样做吗?

谢谢, 麦克

修改

我发现has_many有回调,所以我想我可能会定义这样的关系:

has_many :awesome_friends,
         :class_name => "Friend",
         :conditions => {:awesome => true},
         :before_add => Proc.new{|p,c| c.awesome = true},
         :before_remove => Proc.new{|p,c| c.awesome = false}

虽然,它开始觉得我可能只是在实现其他一些现有的设计模式。也许我应该继承AwesomeFriend&lt;朋友?最终我需要一些has_many关系,并且子类化使所有额外文件变得混乱..

编辑2:

好的,感谢所有评论的人!我最终把上面的方法整理成了一个漂亮的小ActiveRecord扩展,'has_many_of_type'。其作用如下:

has_many_of_type :awesome_friends, :class_name => "Friend", :type=>:awesome

只是将for_many转换为具有适当条件的before_many,before_add和before_remove params(并假设存在名为friend_type的列)。

3 个答案:

答案 0 :(得分:3)

您需要使用:

my_user.awesome_friends.create(:name=>'jim')my_user.awesome_friends.build(:name=>'jim')

在文档中 has_many(:条件)

如果使用散列,则关联记录创建的作用域。 has_many:posts,:conditions =&gt; {:published =&gt; true}将使用@ blog.posts.create或@ blog.posts.build创建已发布的帖子。

答案 1 :(得分:1)

一件事情是:class_name而不是:class

答案 2 :(得分:1)

这不是我不认为的错误。 :conditions hash仅确定了查询对象的方式。但我认为假设您在集合中填充的任何对象都制作以符合条件是不合理的。

在你的简单例子中,它是有道理的,但你也可以在那里放置更复杂的逻辑。

文档似乎也很清楚:

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

  

:conditions

     

指定关联对象必须满足的条件才能包含为WHERE SQL片段,例如authorized = 1