【问题标题】:Rails: Displaying published items and unpublished items of current user as ActiveRecord::RelationRails:将当前用户的已发布项目和未发布项目显示为 ActiveRecord::Relation
【发布时间】:2016-08-22 10:05:29
【问题描述】:

我想知道是否可以同时做以下两件事:

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

【问题讨论】:

  • 当您的问题得到解决时,请考虑接受通知其他人的答案。

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


【解决方案1】:

根据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 这样的 gem。

3) 使用arel

4) 等待 Rails 5 中的 .or 语法。

【讨论】:

    【解决方案2】:

    我明白了,您正试图从当前用户那里找到未发布的项目。在我的范围内你可以做到。

    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
    

    #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
    

    【讨论】:

    • @itemsArray,所以我不能做@items.find(params[:id])
    • @items = Item.published 成为对象数组后,您无法使用 activerecord 方法找到它。那也是索引页,你是怎么得到params[:id]的,你搜索它吗?
    • 是的,当然。我能。但这不是我会得到的。查看其他答案。谢谢。
    • 是的,我明白了。可能我误解了这个问题。很高兴你修好了。
    【解决方案3】:

    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)
    }
    

    【讨论】:

    • 谢谢,你让我开心!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-05
    • 2012-04-13
    • 2023-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多