Rails 4:范围仅在用户未登录

时间:2015-09-22 14:27:52

标签: ruby-on-rails

我想使用像

这样的东西
scope :published, -> { where(:published => true) }
仅当用户未登录时,才能在我的文章模型

。如果用户已登录,那么我想显示所有文章。我意识到Article模型本身无法访问Devise的user_signed_in?方法,所以这个逻辑应该存在于控制器中。

问题是在控制器中它会导致很多冗余,因此:

def index
  if params[:search].present?
    @search = params[:search]
    if user_signed_in?
      @articles = Article.where('title LIKE ? OR body LIKE ?', "%#{@search}%", "%#{@search}%")
    else
      @articles = Article.published.where('title LIKE ? OR body LIKE ?', "%#{@search}%", "%#{@search}%")
    end
  elsif params[:uid].present?
    @user = User.find(params[:uid])
    if user_signed_in?
      @articles = @user.articles.order :created_at
    else
      @articles = @user.articles.published.order :created_at
    end
  else
    if user_signed_in?
      @articles = Article.all.desc
    else
      @articles = Article.published.desc
    end
  end
end

我是否有更好的方法可以避免冗余,但在使用published范围之前始终检查用户是否已登录?

由于

2 个答案:

答案 0 :(得分:1)

您应该考虑使用pundit,您可以通过这种方式确定访问控制范围。

您可以将current_user传递给您的范围。

scope :search, -> (current_user) { where(published: [(current_user.present? ? false : true), true]) }

https://stackoverflow.com/a/16588246/1162683

答案 1 :(得分:0)

首先,将第二个where子句提取到自己的范围内。这将使事情更容易重复使用。

其次,ActiveRecord查询是可组合和懒惰的。这意味着您可以将中间查询保存到变量中,然后附加范围。

class Article
  scope :search, -> {|search| where('title LIKE ? OR body LIKE ?', "%#{@search}%", "%#{@search}%") }
....
end

class ArticlesController
  def index
    articles = Article.search(params[:search])
    articles.published if user_signed_in?
  end
end

像这样的东西