我有一个正在使用的数据库结构,其中Node
与Interviewees
中的两个可能字段之一(clientnode_id
或caregivernode_id
)相关:
tbl_nodes
+----+-----------+
| id | node_Name |
+----+-----------+
| 5 | some name |
+----+-----------+
tbl_interviewees
+----+---------------+------------------+
| id | clientnode_id | caregivernode_id |
+----+---------------+------------------+
| 1 | 5 | NULL |
+----+---------------+------------------+
我只是想在Node模型中定义一个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)
我目前尝试了以下链接的建议,但没有成功(大多数使用不推荐使用的语法):
轨道3:在模型中使用带作用域的lambda
轨道具有动态条件(_Mny)
http://guides.rubyonrails.org/association_basics.html#belongs-到关联引用轨道具有多种条件(_M)
可能只是语法上的一些麻烦,所以任何帮助都将不胜感激。我知道这是错误的,但这是我最近的一次尝试:
class Node < ActiveRecord::Base
self.table_name_prefix = :tbl_
has_many :interviewees, -> { where("clientnode_id=? OR caregivernode_id=?", self.id, self.id) }
end
试试这个
@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
我希望这会有所帮助。
@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和.enabled方法名称并保持惯例。干杯