Ruby on rails Rails 2.3.8命名范围链接

Ruby on rails Rails 2.3.8命名范围链接,ruby-on-rails,named-scope,Ruby On Rails,Named Scope,我有下面的嵌套if语句hairball,我想知道是否有一种更有效的方法来编写这段代码(更少的代码行不需要那么多条件) 每个方法都在模型中命名为_范围 box = (params[:b] ? params[:b] : "inbox") show = (params[:s] ? params[:s] : "all") if box == "inbox" if show == "all" @messages = @current_user.received_messages.all

我有下面的嵌套if语句hairball,我想知道是否有一种更有效的方法来编写这段代码(更少的代码行不需要那么多条件)

每个方法都在模型中命名为_范围

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
我的想法是,我可以使用一种“调用”类型的方法来实现box和show之类的功能

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

呃,我应该多花点时间玩玩。。正如我所想,我只是使用了错误的方法

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

这就是我想出来的,除非大家都同意这是最好的-还有其他想法吗?


您的答案非常接近,但无法转换
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)

这假设您取消了
。您在原始代码中为所有选项使用的所有
,这些选项在您的答案中消失了。

您可以使用rails 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
参考资料:


让我想知道,如果选择“发送”框,而不是“全部”,会发生什么情况。是的,我实际上改变了链接,这样:b以接收和发送消息的形式出现,但我喜欢框\u scope=case gig您在那里的表演哈哈,谢谢!问题:box_scope如何以零结束?如果一个未知值进入,它不是未定义的吗?对,我们想确保它是一个过滤器选项,否则只显示“all”@Rabbott,在Ruby中,all
case
if
块在没有任何条件匹配时返回
nil
。请执行
box=params[:b:][124; |“received\u messages”
而不是三元语句。实际上我只是更改了它,因为我有.include?()我根本不需要| |。如果已经检查了参数是否包含在数组中,则不需要检查它是否存在。它将检查是否包含
nil
,当不存在时返回
false
。我不知道作用域方法,这基本上是rails 3中arel magic之前的步骤吗?所以我可以创建查询,然后在附加所有条件后运行它?我已经添加了一些对该方法的引用。观看指定的Railscast了解更多信息。太棒了,谢谢!这是对rails 2.3.9的补充吗?在2.3.8中不可用?在2.3.x中也可用。
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