业务逻辑是这样的:用户通过一个连接表在一个船上,我想我们称这个模型为一个Ticket。但是,当用户实例想要检查船上还有其他人时,有一个条件是询问该用户是否有权查看船上的所有人或船上的某些人。如果用户可以看到每个人,则正常交易是正常的:some_user.boats.first.users
返回所有用户的船票。但是对于一些用户来说,唯一在船上的人(就他们而言)就是人,比如餐厅。因此,如果用户的票证是“标记的”(使用acts_as_taggable
风格系统)和“餐厅”,则唯一从some_user.boats.first.users
返回的用户应该是带有标记为“餐厅”的票证的用户。使用单例类动态覆盖/添加一个ActiveRecord关联
只是为了记录,我并没有试图从getgo中设计出疯狂的东西 - 我试图将这个任意分组嵌入到(大部分)已存在的系统中。 所以我们有:
class User
has_many :tickets
has_many :boats, :through => :tickets
end
class Ticket
belongs_to :user
belongs_to :boat
end
class Boat
has_many :tickets
has_many :users, :through => :tickets
end
起初,我以为我可以有条件地修改虚拟类,如:
singleton = class << a_user_instance ; self ; end
singleton.class_eval(<<-code
has_many :tickets, :include => :tags, :conditions => ['tags.id in (?)', [#{tag_ids.to_s(:db)}]]
code
)
这得一路下跌到生成SQL,但产生的时候,它生成SQL中结束:
LEFT OUTER JOIN "tags" ON ("tags"."id" = "taggings"."tag_id") WHERE ("tickets"._id = 1069416589 AND (tags.id in (5001,4502)))
我试着挖周围的ActiveRecord的代码,但我无法找到任何地方使得w应在上面的SQL中用'下划线'加上'id'前缀。我知道当一个ActiveRecord类被加载时会加载关联,并且我认为它与单例类相同。 耸肩。
我也用一个alias_method_chain
像:
singleton = class << a_user_instance ; self ; end
singleton.class_eval(<<-code
def tickets_with_tag_filtering
tags = Tag.find(etc, etc)
tickets_without_tag_filtering.scoped(:include => :tags, :conditions => {:'tags.id' => tags})
end
alias_method_chain :tickets, :tag_filtering
code
)
不过,虽然这种方法产生所需门票,任何加入这些门票中的类,而不是虚拟类中使用的条件。 some_user.boats.first.users
返回所有用户。
任何类型的评论将被赞赏,特别是如果我用这种方法吠叫错误的树。谢谢!
你是对的:我只是要实现一些非常类似的事情,编辑现有的代码,并避免把我的整个胸部放在一个无限力量的恶习中。 另外,我追踪了singleton类中的下划线问题:ActiveRecord 2.3 reflection.rb中的第241行。如果这条线是: `active_record.class_name.foreign_key` 而不是 `active_record.name.foreign_key` 一切都将正常工作。 嗨,谢谢你的帮助和建议。对此,我真的非常感激。 – narsk 2009-06-08 14:49:29