我有模特爸爸,妈妈和小孩。我的妈妈有一个名为is_online
的布尔属性。现在我正在做一个这样的分页链:
def show
@dad = Dad.find(params[:dad_id])
@kids = @dad.kids.online.paginate(:page => params[:page])
end
请允许我查看爸爸妈妈在线的孩子名单。
我的模型设置如下:
class Kid < ActiveRecord::Base
belongs_to :dad
belongs_to :mom
scope :online, joins(:mom).where("moms.is_online = ?", true)
end
class Dad < ActiveRecord::Base
has_many :kids
end
class Mom < ActiveRecord::Base
has_many :kids
end
我遇到的问题是,这并没有让这个爸爸的孩子和在线妈妈一起回来,而是回归所有爸爸。如何才能使范围正确?
修改
SELECT DISTINCT "kids"."dad_id" FROM "kids"
=> [14, 25, 27, 8, 12, 17, 28, 1, 15, 10, 26, 11, 4, 18, 30, 16, 6, 19, 29, 2, 21, 3, 23, 31, 20, 5, 13, 22, 9, 7, 24]
Kid Load (1.5ms) SELECT "kids".* FROM "kids" INNER JOIN "moms" ON "moms"."id" = "kids"."mom_id" WHERE (moms.is_online = 't')
=> #<ActiveRecord::Relation [
#<Kid id: 7, dad_id: 1, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">,
#<Kid id: 21, dad_id: 2, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">,
#<Kid id: 35, dad_id: 3, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">,
#<Kid id: 49, dad_id: 4, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">,
#<Kid id: 63, dad_id: 5, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">,
#<Kid id: 77, dad_id: 6, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">,
#<Kid id: 91, dad_id: 7, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">,
#<Kid id: 105, dad_id: 8, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">,
#<Kid id: 119, dad_id: 9, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">,
#<Kid id: 133, dad_id: 10, mom_id: 5, created_at: "2014-04-28 16:10:48", updated_at: "2014-04-28 16:10:48">, ...]>
答案 0 :(得分:3)
修改强>
正如 @KirtiThorat 所提到的,OP的范围方法无效的真正的原因是由于Rails 4的发布导致ActiveRecord范围定义发生了变化具体来说,根据upgrading Rails guide:
Rails 4.0要求范围使用可调用对象,例如Proc或lambda
考虑到这一点,只需重新定义lambda中的:online
范围定义就可以解决问题:
scope :online, -> {joins(:mom).where("mom.is_online = ?", true)}
原始回答:
您最好的选择是使用merge
方法:
def show
@dad = Dad.find(params[:dad_id])
@kids = @dad.kids.merge(Kid.online)
end
由于ActiveRecord文档定义merge
:
合并(
other
)公开
如果other
是ActiveRecord :: Relation,则合并来自other
的条件。如果other
是数组,则返回表示结果记录与<{1}}的交集的数组。
因此,由于other
找到两个数组的交集,在这种情况下,merge
的孩子和@dad
的数组在线Kid
s ,这将产生包含Mom
作为Kid
的所有@dad
和Dad
Mom
的数组。
也很高兴知道也可以使用数组交集速记方法is_online
:
&
答案 1 :(得分:3)
更改您的scope
,如下所示:
scope :online, -> { joins(:mom).where("moms.is_online = ?", true) }
不知何故,在Rails 4
中,您的范围online
未被链接到使用@dad.kids
形成的查询。以上是定义 Scope in Rails 4
答案 2 :(得分:1)
我不确定它是否会起作用,但您可以尝试以下方法::
class Dad < ActiveRecord::Base
has_many :kids
has_many :kids_with_online_mom, class_name: `Kid`, through: :mom, joins(:mom).where("moms.is_online = ?", true)
end
如果有效,只需@dad.kids_with_online_mom
,您就可以获得所需的输出。