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

Sch*_*ems 2 ruby controller ruby-on-rails

我经常构建控制器,我想要多种方法(除索引,编辑,显示等).大多数情况下,我想要的动作可以归结为show,因为它们是简单的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
Run Code Online (Sandbox Code Playgroud)

显示的一切

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

单独的方法

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

真正的问题是,这些技术中的哪一个不那么 糟糕.

Joh*_*ibb 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
Run Code Online (Sandbox Code Playgroud)

这将调用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
Run Code Online (Sandbox Code Playgroud)

然后在routes.rb中:

FOLLOW_ACTIONS.each do |action|
    match action.to_sym => "controller##{action}"
end
Run Code Online (Sandbox Code Playgroud)