我有一个Rails 4.1.7应用程序,我们有themes
和class User < ActiveRecord::Base
has_many :themes
end
class Theme < ActiveRecord::Base
belongs_to :user
end
:
user_id
现在,用户可以创建一些自己的主题(然后这些主题会将id
设置为用户的user_id
),或者可以使用任何预定义的主题(拥有{ {1}}设置为null
)
我想要做的是:以某种方式更改has_many
关联,以便在我调用@user.themes
时,这会为我带来预设主题以及用户的主题。
我尝试过:
1)定义实例方法而不是has_many
关联:
class User < ActiveRecord::Base
def themes
Theme.where user_id: [id, nil]
end
end
但是因为我想用用户(includes(:themes)
)急切加载主题,但这并不是真的。
2)使用某个范围(has_many :themes, -> { where user_id: nil }
),但它提供my ... WHERE user_id = 123 AND user_id IS NULL
等mySql查询,返回空。我想使用Rails5我可以用has_many :themes, -> { or.where user_id: nil }
之类的东西来做,但是现在不能改变Rails版本。
答案 0 :(得分:1)
您可以将super
(返回相关主题)与预定义的(user_id
为nil
)结合使用:
class User < ActiveRecord::Base
def themes
Theme.where(id: super.ids + Theme.where(user_id: nil).ids)
end
end
答案 1 :(得分:-1)
自从发布我的问题以来,我尝试了许多方法来实现我的目标。一个很有趣,我想,值得一提:
我尝试使用unscope或rewhere解除has_many
之间的联系,看起来像这样:
has_many :themes, -> user = self { # EDIT: `= self` can even be omitted
u_id = user.respond_to?(:id) ? user.id : user.ids
unscope(where: :user_id).where(user_id: [u_id, nil])
# or the same but with other syntax:
rewhere(user_id: [u_id, nil])
}
当我尝试@user.themes
时,它就像奇迹一样,并提供了以下mySql行:
SELECT `themes`.* FROM `themes`
WHERE ((`themes`.`user_id` = 123 OR `themes`.`user_id` IS NULL))
但是当我试图加载它时(为什么我开始研究),它只是拒绝取消查询,并给出了相同的旧user_id = 123 AND user_id = NULL
行。
毕竟,@ Ilya的评论使我和this回答相信,使用has_many
进行查询是一回事,但它有其他方面,例如分配,并覆盖它为了一个人的利益可以破坏许多其他事情。
所以我决定继续使用我的好方法,只是我给它一个更具体的名称,以避免将来混淆:
def available_themes
Theme.where user_id: [id, nil]
end
至于@ AndreyDeineko的回答 - 因为他一直拒绝回答我的问题,总是回答从未被问过的问题 - 我仍然无法理解为什么他的方法(与available_themes
有同样的结果,但是使用3个额外的查询)将是一个更好的解决方案。