2011-06-07 77 views
2

我有以下嵌套的if語句hairball,我想知道是否有更有效的方式來編寫此代碼(不需要這麼多條件的代碼行)Rails 2.3.8 named_scope鏈接

每種方法都named_scopes模型中..

box = (params[:b] ? params[:b] : "inbox") 
show = (params[:s] ? params[:s] : "all") 

if box == "inbox" 
    if show == "all" 
    @messages = @current_user.received_messages.all 
    elsif show == "unread" 
    @messages = @current_user.received_messages.unread.all 
    elsif show == "read" 
    @messages = @current_user.received_messages.read.all 
    elsif show == "starred" 
    @messages = @current_user.received_messages.starred.all 
    else 
    @messages = [] 
    end 
elsif box = "sent" 
    @messages = @current_user.sent_messages.all 
else 
    @messages = [] 
end 

我的想法是,我可以用一個「呼叫」型方法的框,顯示像

@current_user.received_messages.call(:box).call(:show).all 

也許..?

哎,應該花一點更多的時間玩了..其正當我以爲,我只是使用了錯誤的方法SOLUTION

@current_user.send(box).send(show) 

回答

3

您可以使用軌道2.3.8的scoped()方法鏈範圍:

main_method = case (params[:s]||"inbox") 
when "inbox" 
    :received_messages 
when "sent" 
    :sent_messages 
end 
# create a scope. Don't execute the scope yet. 
scope = @current_user.send(main_method).scoped({}) if main_method 

# now chain the scope if needed 
scope = begin 
    if ["unread", "read", "starred"].include?(params[:s]) 
    scope.send(params[:s]) 
    elsif((params[:s] || "all") == "all") 
    scope 
    end 
end if main_method == :received_messages 

@messages = scope.nil? ? [] : scope.all 

參考:

Scoped method source in Rails 2.3.x

Rails casts on Anonymous scopes in 2.3.x

+0

我不知道範圍的方法,這基本上是在軌道3之前arel魔術的步驟?所以我可以創建查詢,然後在附加所有條件後運行它? – Rabbott 2011-06-08 15:46:23

+0

我已經添加了一些對該方法的引用。觀看指定的Railscast以獲取更多信息。 – 2011-06-08 16:27:37

+0

真棒謝謝你!這是除了軌道2.3.9?在2.3.8中不可用? – Rabbott 2011-06-08 20:21:46

0

這是我想通了,我不會標記我自己的答案是正確的,除非大家同意這是最好的 - 10其他想法?

if params[:b].present? && ["received_messages", "sent_messages"].include?(params[:b]) 
    box = params[:b] 

    if params[:s].present? && ["all", "unread", "starred"].include?(params[:s]) 
    show = params[:s] 
    else 
    show = "all" 
    end 

    @messages = @current_user.send(box).send(show) 
else 
    @messages = [] 
end 
+1

請不要'箱=參數[ :b:] || 「received_messages」而不是三元語句。 – 2011-06-07 23:40:04

+0

我只是改變了它,因爲我有.include?()我不需要||。在所有的.. – Rabbott 2011-06-07 23:42:41

+0

你不需要檢查param的存在,如果你已經檢查它包含在一個數組中。它會檢查是否包含'nil',當不存在時它將返回'false'。 – 2011-06-08 00:56:32

0

你的答案是非常接近,但它無法轉換box值。

box = params[:b] || 'inbox' 
show = params[:s] || 'all' 

box_scope = case box 
    when 'inbox' then 'received_messages' 
    when 'sent' then 'sent_messages' 
end 
show_scope = show # no convertion needed at this point, maybe in the future 

# If box_scope is nil, don't query 
@messages = box_scope.nil? ? [] : @current_user.send(box_scope).send(show_scope) 

這是假設你弄死了.all您正在使用的原代碼所有選項,消失在你的答案。

+0

讓我想知道如果用'all'以外的任何* show *選項選中'sent'框,會發生什麼情況。 – 2011-06-07 23:32:39

+0

是的,我實際上最終改變了鏈接,所以:b進來作爲收到和發送消息,但我喜歡box_scope =案例演出你去那裏哈哈,謝謝!問題:box_scope如何以零結尾?如果有未知值出現,它會不確定嗎? – Rabbott 2011-06-07 23:34:44

+0

更新到我的實際代碼.. – Rabbott 2011-06-07 23:37:04