控制器最佳实践:Show中的多个方法或多个案例

时间:2011-05-10 19:05:16

标签: ruby-on-rails ruby controller

我经常构建控制器,我想要多种方法 (除了索引,编辑,显示等)。大部分时间都是我的行动 由于它们是简单的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

展示中的一切

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

单独的方法

  • 更多路由
  • 不干
  • 简便方法查找
  • 更容易阅读个别方法

真正的问题是,这些技术中的哪一种 less 坏。

1 个答案:

答案 0 :(得分:7)

我会做类似的事情:

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]中传递的任何方法,只要它在白名单中(以防止任意代码注入)。

如果拥有单独的路线对您有好处(更好的网址?),您还可以使用以下内容动态生成方法和路线:

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