假设我的rails 3.1项目中有一些activerecord模型,如下所示:
class Component < ActiveRecord::Base
has_many :bugs
end
class Bug < ActiveRecord::Base
belongs_to :component
belongs_to :project
scope :open, where(:open => true)
scope :closed, where(:open => false)
end
class Project < ActiveRecord::Base
has_many :bugs
has_many :components_with_bugs, :through => :bugs, :conditions => ["bugs.open = ?", true]
end
简而言之:我有一个has_many通过关联(components_with_bugs
),我想在其中确定“通过”模型的范围。目前我正在通过复制范围的代码来做到这一点。
有没有办法定义这有很多通过关联(components_with_bugs
),这样我可以在直通模型上重用Bug.open
范围,同时仍然在单个数据库查询中加载组件? (我想象的是:conditions => Bug.open
)
答案 0 :(得分:2)
Rails 4回答
鉴于你有:
class Component < ActiveRecord::Base
has_many :bugs
end
class Bug < ActiveRecord::Base
belongs_to :component
belongs_to :project
scope :open, ->{ where( open: true) }
scope :closed, ->{ where( open: false) }
end
您有两种可能性:
class Project < ActiveRecord::Base
has_many :bugs
# you can use an explicitly named scope
has_many :components_with_bugs, -> { merge( Bug.open ) }, through: :bugs, source: 'component'
# or you can define an association extension method
has_many :components, through: :bugs do
def with_open_bugs
merge( Bug.open )
end
end
end
调用projet.components_with_bugs
或project.components.with_open_bugs
将触发相同的SQL查询:
SELECT "components".* FROM "components"
INNER JOIN "bugs" ON "components"."id" = "bugs"."component_id"
WHERE "bugs"."project_id" = ? AND "bugs"."open" = 't' [["project_id", 1]]
哪一个更好用,取决于您的应用程序。但是如果你需要在同一个协会上使用很多范围,我猜association extensions可能会更清楚。
真正的魔术是用merge完成的,正如名称所示,它允许你合并另一个ActiveRecord :: Relation的条件。在这种情况下,它负责在SQL查询中添加AND "bugs"."open" = 't'
。
答案 1 :(得分:0)
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html指定
:conditions 指定关联对象必须满足的条件才能包含为WHERE SQL片段,例如authorized = 1。
因此你可以这样做:
class Project < ActiveRecord::Base
has_many :bugs
has_many :components_with_bugs, :through => :bugs do
def open
where("bugs.open = ?", true)
end
end
end
编辑:
你不能指定另一个模型的范围作为条件。在你的情况下,你已经实施的方式是正确的。你可以实现另一种方式
has_many :components_with_bugs, :through => :bugs #in this case, no need to use the relation.
def open_bugs
self.bugs.openn #openn is the scope in bug. dont use name 'open'. its a private method of Array.
end
答案 2 :(得分:0)
除了您的范围外,请将默认范围写为:
“通过”模型中的 default_scope where(:open => true)
错误。
class Bug < ActiveRecord::Base
belongs_to :component
belongs_to :project
default_scope where(:open => true)
的
scope :open, where(:open => true)
scope :closed, where(:open => false)
end
在项目模型中删除:conditions =&gt; [“bugs.open =?”,true]
class Project < ActiveRecord::Base
has_many :bugs
has_many :components_with_bugs, :through => :bugs
end
我认为上述内容对您有用。
答案 3 :(得分:0)
尝试使用以下内容。
has_many :components_with_bugs, :through => :bugs do
Bug.open
end
答案 4 :(得分:0)
你不能用这样的东西吗?
has_many :components_with_bugs, :through => :bugs, :conditions => Bug.open.where_values
我没有测试过,只是提出了一条调查路径