【问题标题】:How to make a Rails 4 ActiveRecord model with has_many that joins on a custom WHERE clause with an OR condition如何使用 has_many 制作带有 OR 条件的自定义 WHERE 子句的 Rails 4 ActiveRecord 模型
【发布时间】:2016-01-15 02:46:46
【问题描述】:

我正在使用一个数据库结构,其中NodeInterviewees 中的两个可能字段之一相关(clientnode_idcaregivernode_id):

tbl_nodes
+----+-----------+
| id | node_Name |
+----+-----------+
|  5 | some name |
+----+-----------+

tbl_interviewees
+----+---------------+------------------+
| id | clientnode_id | caregivernode_id |
+----+---------------+------------------+
|  1 |             5 |             NULL |
+----+---------------+------------------+

我只是想在节点模型中定义一个has_many,其中包含来自任一字段的匹配项。等效的 SQL 将是:

SELECT * FROM tbl_nodes LEFT JOIN tbl_interviewees ON (tbl_nodes.id=tbl_interviewees.clientnode_id OR tbl_nodes.id=tbl_interviewees.caregivernode_id)

我目前尝试了以下链接的建议无济于事(大多数使用不推荐使用的语法):

Rails 3: Use of lambda with scopes in model

Rails has_many with dynamic conditions

http://guides.rubyonrails.org/association_basics.html#belongs-to-association-reference Rails has_many conditions

可能只是语法有些复杂,因此我们将不胜感激。我知道这是错误的,但这是我最近的尝试:

class Node < ActiveRecord::Base
  self.table_name_prefix = :tbl_
  has_many :interviewees, -> { where("clientnode_id=? OR caregivernode_id=?", self.id, self.id) }
end

【问题讨论】:

    标签: ruby-on-rails ruby activerecord


    【解决方案1】:

    试试这个

    @nodes = Node.joins(:interviewees).where("interviewees.clientnode_id=:node_id OR interviewees.caregivernode_id=:node_id", node_id: <your id>)
    

    通过scope,在model中写入带参数的作用域

    class Node < ActiveRecord::Base
      has_many :interviewees
      scope :interviews_by_node, ->(node_id) { joins(:interviewees).where("interviewees.clientnode_id=:node_id OR interviewees.caregivernode_id=:node_id", node_id: node_id)
    end
    

    controller 操作中调用scope

    class NodesController < ApplicationController
    
      def index
        @nodes = Node.interviews_by_node(5)  
      end
    
    end
    

    我希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      @Nitin 谢谢!我能够调整您的想法以获得我想要的行为如下:

      class Node < ActiveRecord::Base
        # replaces using a "has_many :interviewees" since it is joined off 2 different fields
        def interviewees
          Interviewee.by_node(self.id)
        end
      end
      
      class Interviewee < ActiveRecord::Base
        # called by Node model to get Interviewee association
        scope :by_node, ->(node_id) { where("clientnode_id=? OR caregivernode_id=?", node_id, node_id) }
      
        # replaces "belongs_to :node" since it is joined off 2 different  fields
        def node
          Node.where("id = ? OR id = ?", self.clientnode_id, self.caregivernode_id)
        end
      end
      

      我觉得这样做有助于保持封装更好一点,因为 Node 不必知道受访者拥有的特定字段。

      这允许我使用相同的 .node 和 .interviewees 方法名称并保持约定。干杯!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多