【问题标题】:Controller best practices: Multiple Methods or Multiple cases in Show控制器最佳实践:Show 中的多种方法或多种情况
【发布时间】:2011-05-10 19:05:16
【问题描述】:

我经常在需要多种方法的地方构建控制器 (除了索引、编辑、显示等)。大多数时候我的动作 欲望可以归结为表演,因为它们是简单的 GET 操作, 但是我不想在任何一个控制器动作中加入太多逻辑。

以下是实现相同目的的两种不同方法的简单示例 东西……

class TwitterFriendController < ApplicationController
  ## lump everything into show?
  def show
    if params[:id] == "follow"
      users = current_user.following
    elsif params[:id] == "follow_me"
      users = current_user.users_who_follow_me
    elsif params[:id] == "following_follow_me"
      users = current_user.following_who_follow_me
    elsif params[:id] == "following_who_do_not_follow_me"
      users = current_user.following_who_do_not_follow_me
    ...
    end
    respond_with do |format|
      format.json do {...}
    end
  end

  ## or split everything out into separate methods, this requires
additional routing
  def following
    ...
  end

  def users_who_follow_me
    ...
  end

  def following_who_follow_me
    ...
  end

  def following_who_do_not_follow_me
    ...
  end
end

节目中的一切

  • 一种方法中的大量逻辑
  • 干燥? # 逻辑需要大量额外代码
  • 减少路由

单独的方法

  • 更多路由
  • 不干燥
  • 简单的方法查找
  • 更易于阅读单个方法

所以真正的问题是,其中一种技术 不好。

【问题讨论】:

    标签: ruby-on-rails ruby controller


    【解决方案1】:

    我会这样做:

    FOLLOW_WHITELIST = %w[ follow follow_me following_follow_me following_who_follow_me following_who_do_not_follow_me ]
    
    def show
        if FOLLOW_WHITELIST.include? params[:id]
            users = current_user.send params[:id].to_sym
        end
        respond_with do |format|
            format.json do {...}
        end
    end
    

    这将调用 params[:id] 中传递的任何方法,只要它在白名单中(以防止任意代码注入)。

    如果有单独的路由对您来说是一个加分项(更好的 url?),您还可以使用以下内容动态生成方法和路由:

    class TwitterFriendController < ApplicationController
    
        FOLLOW_ACTIONS = %w[ follow follow_me following_follow_me following_who_follow_me following_who_do_not_follow_me ]
    
        FOLLOW_ACTIONS.each do |action|
            define_method action do
                users = current_user.send action.to_sym
                respond_with do |format|
                  format.json do {...}
                end
            end
        end
    
    end
    

    然后在 routes.rb 中:

    FOLLOW_ACTIONS.each do |action|
        match action.to_sym => "controller##{action}"
    end
    

    【讨论】:

    • 非常优雅。但是,一旦其中一种方法需要一些不能或不应该放入模型中的额外逻辑,您就几乎失去了所有收益。我也不会在生产机器上的控制器方法上定义方法,它在定义时将所有局部变量保持在范围内并使用(稍微)更多内存。在我宣布正式“答案”之前,如果有人有任何其他想法,我有兴趣听听
    • 我不确定您还在等待什么其他类型的解决方案。一旦其中一种方法需要额外的逻辑,为它使用不同的方法就不再违反“DRY”原则。
    • 我已经确定了演示者模式和单一的显示方法。没有“解决方案”,但我想我会得到一些不同的答案。感谢您的意见,这里有几点。
    猜你喜欢
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 2014-03-18
    • 2017-03-29
    相关资源
    最近更新 更多