2015-09-22 55 views
2

簽署了範圍,我想在我的文章模型使用類似軌道4:只有當用戶沒有

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範圍?

由於

回答

1

你應該考慮使用權威人士,你可以精確地用這種方式進行訪問控制範圍的訪問。

您可以將current_user傳遞給您的範圍。

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

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

+0

謝謝,Pundit可能正是我需要保持這種簡單。 – DaniG2k

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 

類似的東西

+0

對不起,我也不是很清楚。我的問題是:我怎麼能做這樣的'scope:published, - > {user_signed_in? ?所有:其中(:公佈=>真)}' 這是不可能的模型內,所以我想知道是否有更好的方法來做到這一點在控制器 – DaniG2k

+0

這不是一個最佳做法調用user_signed_in?方法,因爲它是一個控制器業務 所以我認爲@Srdjan建議的重構代碼是相當不夠的 –

+0

即使沒有'user_signed_in?'問題,操作已經做得太多了。爲什麼不分成3個獨立的動作,'index'運行'else'子句中的代碼,'search',執行搜索代碼,然後執行任何'uid'。 –