2011-06-07 55 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