这对我来说似乎是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的列)。
答案 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
。