我想使用像
这样的东西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
范围之前始终检查用户是否已登录?
由于
答案 0 :(得分:1)
您应该考虑使用pundit,您可以通过这种方式确定访问控制范围。
您可以将current_user传递给您的范围。
scope :search, -> (current_user) { where(published: [(current_user.present? ? false : true), true]) }
答案 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
像这样的东西