我想知道是否可以同时执行以下两项操作:
published
的所有项目。我有这段代码:
# Item model
scope :published, -> { where(status: 'published') }
scope :unpublished, -> { where.not(status: 'published') }
scope :by_user, -> (user_id) { where(user: user_id) }
# Item controller
def index
@items = Item.published + Item.unpublished.by_user(current_user.id)
end
问题是@items
是Array
,但我想要ActiveRecord::Relation
。
如果你想知道为什么我需要这个,这是一个简单的答案:
@items.find(params[:id])
答案 0 :(得分:2)
基于Rails: How to chain scope queries with OR instead of AND?中的讨论,我认为您至少有四种选择:
1)编写一个结合了现有范围的范围,例如:
scope :published_or_unpublished_by_user, -> (user_id) { where('status = ? OR (status != ? and user = ?)', 'published', 'published', user_id) }
2)使用像squeel这样的宝石。
3)使用arel。
4)等待Rails 5中的.or
语法。
答案 1 :(得分:2)
Rails 4.x还不支持OR
或UNION
查询,因此我建议将其他范围与子查询组合在一起的新范围(数据库应该能够优化它们):
# in the model
scope :visible_for_user, ->(user) {
where(
'items.id IN (?) OR items.id IN (?)',
Item.published, Item.unpublished.by_user(user.id)
)
}
# in the controller
@items = Item.visible_for_user(current_user)
请注意,如果要联合现有范围,以上是一般解决方案。在此特定示例中,您可以通过优化范围获得更好的性能:
scope :visible_for_user, ->(user) {
where("items.status = 'published' OR items.user_id = ?", user.id)
}
答案 2 :(得分:1)
我知道,您正在尝试从当前用户中查找未发布的项目。你可以在我的范围内完成。
scope :current_user_not_published, ->(user_id)
{where('status != ? AND user = ?', 'published', user_id)}
<强>控制器:强>
# Item controller
def index
@published_items = Item.published
@current_user_unpublished_utems = Item.current_user_not_published(current_user.id)
end
OR
#in this case it will be @items[0] published, @items[1] c.not_published
def index
@items = [Item.published, Item.current_user_not_published(current_user.id)]
end