Rails:将当前用户的已发布项目和未发布项目显示为ActiveRecord :: Relation

时间:2016-04-27 21:23:27

标签: ruby-on-rails ruby activerecord rails-activerecord

我想知道是否可以同时执行以下两项操作:

  • 查看状态为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

问题是@itemsArray,但我想要ActiveRecord::Relation

如果你想知道为什么我需要这个,这是一个简单的答案:

@items.find(params[:id])

3 个答案:

答案 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还不支持ORUNION查询,因此我建议将其他范围与子查询组合在一起的新范围(数据库应该能够优化它们):

# 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