如何通过中间模型对象有条件地获取某些模型的对象及其关联模型的对象?然后,这将用于生成JSON(通过to_json
)。
以下是更通用的设置:
class JobSet < ActiveRecord::Base
belongs_to :job_system
has_many :resources, through => :job_system
has_many :jobs
...
end
class JobSystem < ActiveRecord::Base
has_many :job_sets
has_many :resources
...
end
class Resource < ActiveRecord::Base
belongs_to :job_system
has_many_and_belongs_to_many :jobs
...
end
class Job < ActiveRecord::Base
belongs_to :job_system
belongs_to :job_set
has_many_and_belongs_to_many :resources
...
end
我想要做的是获取所有资源及其相应的作业,但只获取属于特定作业集的作业。
更新:即使资源没有与之关联的任何作业,我仍然希望将其与其余资源一起使用。目的是显示分配给它们的任何作业的所有资源。
看起来我可以在使用conditions
时设置through
,但我似乎无法弄清楚当它是我之后的下一个对象关联时如何做到这一点......
这类问题有一个好名字吗?有没有简单的方法呢?
UPDATE 2 :似乎有一些解决方案在控制器中运行良好,但我在视图中使用to_json来预加载canvas元素。当我这样做时,它似乎自动包含所有工作:
var resources = <%= @resources.to_json(:include => {:jobs => {:only => :id}}) %>;
手动SQL JOIN会对此有所帮助吗?
答案 0 :(得分:1)
我想我知道你在追求什么。我唯一要问的是,如果一个资源在这个特定的工作集中没有任何工作,它是否还应该被包括在内?
无论如何,这是一种方法:
@resources = Resource.all(:include => :jobs,
:conditions => ["jobs.job_set_id = ?", @job_set.id])
这不包括没有与@job_set
关联的作业的资源所以,我的假设完全错了,或者这就是你之后的所在?
好吧,这比我想象的要困难得多。有几个解决方案但我不喜欢。你可以这样做:
@resources = Resource.all
@resources.each do |resource|
resource.jobs.all(:conditions => ["jobs.job_set_id = ?", @job_set_id])
end
但这会导致1 + n个查询号问题给你的数据库带来压力。
您也可以这样做:
@resources = Resource.all(:include => :jobs)
@resources.each do |resource|
resource.jobs.select{ |job| job.job_set_id == @job_set_id }
end
但这会导致服务器端的内存消耗量增加,因为所有作业都是急切加载,然后循环查看哪个匹配job_set_id。
在我看来,找到更好的解决方案的问题是,这应该在SQL JOIN条件中指定,但我认为ActiveRecord不允许我们将其与急切加载一起修改。
答案 1 :(得分:0)
你应该能够以一种非常直接的方式做到这一点,但你可能需要一个特定格式或结构的集合,而不是这里给出的:
@resources = @job_set.resources.include(:jobs)
作为一个注释,我建议不要使用Rails 1样式has_many_and_belongs_to_many
声明。他们使用的连接表不是基于模型的,并且非常难以操作,特别是如果它们具有与它们相关联的元数据,则与更现代的连接模型方法相比。您只需创建一个名为JobResource或ResourceJob的模型,具体取决于您希望如何确定事项的优先级,并构建两个belongs_to
关系以将它们连接在一起。