将复杂的has_many关系移植到Rails> 4.1(没有finder_sql)

Jen*_*ens 5 activerecord ruby-on-rails finder-sql model-associations

我正在将Rails应用程序移植到Rails 4.2.这个Rails应用程序在关联中包含一些相当复杂的手动SQL代码 - 部分是由于DB优化(例如子选择而不是JOIN),部分原因是由于在编写时没有可行的替代方案(Rails 3.0),部分原因是由于缺乏知识(我希望,至少 - 这很容易解决).

示例:InternalMessage类.可以在用户之间发送消息(InternalMessage的收件人和消息的"删除",存储在InternalMessagesRecipients中,因为可以有几个)并且可以读取,回复,转发和删除它们.该关联看起来像这样:

class User < AR::Base
  has_many :internal_messages,
      :finder_sql => "SELECT DISTINCT(internal_messages.id), internal_messages.* FROM internal_messages " +
          ' LEFT JOIN internal_messages_recipients ON internal_messages.id=internal_messages_recipients.internal_message_id' +
          ' WHERE internal_messages.sender_id = #{id} OR internal_messages_recipients.recipient_id = #{id}',
      :counter_sql => 'SELECT count(DISTINCT(internal_messages.id)) FROM internal_messages ' +
          ' LEFT JOIN internal_messages_recipients ON internal_messages.id=internal_messages_recipients.internal_message_id' +
          ' WHERE internal_messages.sender_id = #{id} OR internal_messages_recipients.recipient_id = #{id}'
  # ...
end
Run Code Online (Sandbox Code Playgroud)

关键部分是最后的"OR"子句 - 通过这种关联,我希望获得接收和发送的消息,这些消息与用户表单独连接:

  has_many :sent_messages, -> { where(:sender_deleted_at => nil) }, :class_name => 'InternalMessage', :foreign_key => 'sender_id' #, :include => :sender
  has_many :internal_messages_recipients, :foreign_key => 'recipient_id'
  has_many :rcvd_messages, :through => :internal_messages_recipients,  :source => :internal_message, :class_name => 'InternalMessage'
Run Code Online (Sandbox Code Playgroud)

因为InternalMessage可能有几个收件人(也可以自己发送给发件人).

问:如何将其移植finder_sql到Rails 4.2兼容has_many定义?

Jen*_*ens 4

更新

不久前我了解到这毫无意义。关系has_many必须至少在一个方向上具有单射连接,因此 SQL 子句中的“OR”没有意义。操作应如何CREATE决定满足哪个条件来创建新记录?根据定义,此关系是只读的,因此它不是关系has_many

在这种情况下,一个简单的类方法(或作用域)将是正确的答案,而不是has_many. 要连接多个查询的结果,请使用类似

def internal_messages
  InternalMessage.where( id: sent_message_ids + received_message_ids)
end
Run Code Online (Sandbox Code Playgroud)

保持生成的对象可链接(即@user.internal_messages.by_date等)