我正在构建一个Rails应用程序来管理服务公司的日程安排。
对于这个问题的范围,模型结构是:
客户有很多合同
合同有很多服务
工人有很多服务
在我的查询中,我有一个工人和一个客户,我需要制作一个
@contracts relationship
匹配所有与客户和工作人员共同的合同。
我已经尝试了很多方法,但是如果我通过select {}和循环递归地生成@contracts列表,我获得的数组不是ActiveRecord而且它不能在rails app中使用(例如在erb)。
我被卡住了:/
答案 0 :(得分:1)
假设您有正确的has_many
和belongs_to
关系设置,您的查询可能会是这样的:
Contract.joins(services: :worker)
.where(services: {worker_id: target_worker_id})
.where(contracts: {client_id: target_client_id}).uniq
其中target_worker_id
和target_client_id
是您希望过滤的工作人员和客户。
此查询会将contracts
加入services
表(因为您说"合同有许多服务"),它也将services
表连接到{ {1}}表(因为你说"工人有很多服务")。简而言之,workers
似乎是一个连接表,是多对多关系的结果,因此是连接子句。
编辑:注意services
,这是确保仅加载不同.uniq
个对象所必需的。否则,正如您所经历的那样,由Contract
方法引起的内部联接将基本上创建一个重复的集合。
如果我误解了任何内容,或者您对此答案有其他疑问,请与我联系。
快速注意:你写了我获得了一个不是ActiveRecord的数组,它不能在rails应用程序中使用(例如在erb中)。我不完全清楚你是什么是的,但在控制器中创建的任何实例变量都可以在ERB中使用;它不需要是一个活动的记录对象。如上所述,我不确定这是不是你的意思。
答案 1 :(得分:0)
class Client < ActiveRecord::Base
has_many :conctracts, inverse_of: client, dependent: :destroy
end
class Contract < ActiveRecord::Base
has_many :services
end
class Worker < ActiveRecord::Base
has_many :services
end
class Service < ActiveRecord::Base
belongs_to :worker
belongs_to :contract
has_many :clients, through: contract
scope :workers, ->(*w) {
where(worker_id: w.flatten.compact.uniq)
}
scope :contracts, ->(*c) {
where(contract_id: c.flatten.compact.uniq)
}
end
workers = Worker.all
clients = Client.join(contracts: {services: worker}).merge(Service.workers(workers))