【问题标题】:ActiveRecord Association without Foreign Key没有外键的 ActiveRecord 关联
【发布时间】:2010-10-25 08:39:54
【问题描述】:

我正在尝试建立用户之间的关系模型。用户可以发起关系,也可以从另一个用户接收关系。因此,db中的关系表有外键“initiator_id”和“recipient_id”。
现在,我可以使用以下关联来计算用户发起或接收的关系:

has_many :initiated_relations, :foreign_key => :initiator_id, :class_name => 'Relation', :dependent => :destroy
has_many :received_relations,  :foreign_key => :recipient_id, :class_name => 'Relation', :dependent => :destroy

我想要做的是建立一个关联,它将获取属于用户的所有关系(无论是发起的还是接收的)。尝试以下不起作用,并抱怨缺少“user_id”字段:

has_many :relations, :conditions => 'recipient_id = #{id} or initiator_id = #{id}'

如何创建仅基于条件字段的关联,而不查找默认的foreign_key?或者是否有完全不同的方法来解决这个问题?

【问题讨论】:

    标签: ruby-on-rails activerecord associations


    【解决方案1】:

    从您的 cmets 到 @neutrino 的回答,我了解,您只需要这种“关系”来进行只读操作。如果您使用的是 Rails 3,您可以利用它使用延迟获取的事实。 where() 方法返回 ActiveRecord::Relation 对象,您可以稍后对其进行修改。所以你可以像这样定义一个方法:

    def User < ActiveRecord::Base
      def all_relations
        Relation.where("initiator_id => ? OR recipient_id = ?", id, id)
      end
    end
    

    然后你可以这样做:

    User.all_relations.where(:confirmed => true).all
    

    【讨论】:

    • 这似乎是一个非常优雅的解决方案,是的,我只希望这种关系用于只读目的。但是,我没有使用 Rails 3,所以这对我不起作用:(。+1 是一个很好的答案:)。
    • 作用域很棒,但你不能急切地加载它们
    【解决方案2】:

    好吧,我可以考虑使用finder_sql:

    has_many :relations, :finder_sql => 'select * from relations right outer join users
        on relations.recipient_id = #{id} or relations.initiator_id = #{id}'
    

    除此之外,您可以只编写一个返回两个关系关联的联合数组的方法,但您将失去关联接口的优势(呸)。

    也许有人会想出更好的解决方案。

    【讨论】:

    • 我已经尝试过使用 finder_sql,但是如果有任何其他方法可以实现这一点,我更愿意这样做,因为使用 finder_sql 我会失去所有关联功能。例如:我不能做user.relations.find(:all, :conditions =&gt; {:confirmed =&gt; true}) 或任何其他类似的功能。感谢您的意见,非常感谢。
    • 我认为这行不通。 #{id} 在类级别进行评估,而不是在实例级别。它需要是一个 proc,从 rails v3.2.13 开始,它只支持 :conditions 选项。 Rails 4 在这方面会更好。
    • :finder_sql 已被弃用并从 Rails 4.1 中删除。所以这个解决方案不再起作用了。
    猜你喜欢
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多