2011-05-10 65 views
2

我经常建立控制器,我想要多种方法 (除了索引,编辑,显示等)。大多数情况下,我想要的操作可能会被放在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 

一切都在显示

  • 在一个方法
  • DRY一吨的逻辑?需要路由逻辑
  • 减#很多额外的代码

单独的方法

  • 多个路由
  • 不会干
  • 简易方法查找
  • 更易于读取单个方法

所以再次真正的问题是,这些技术之一是更少 不好。

回答

6

我会做这样的事情:

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为传递[:编号],只要它在白名单(以防止任意代码注入)。

如果有不同的途径是加给你(更好的网址?),你也可以动态生成的方法和途径有这样的事情:

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 
+0

美丽的解决方案 – bruno077 2011-05-10 20:10:56

+0

很优雅。然而,只要其中一种方法需要一些不能或不应该放入模型的额外逻辑,您就会失去所有的收益。我也不会在生产机器上的控制器方法上使用define_method,它在定义时保留了所有局部变量的范围,并使用(稍微)更多的内存。如果任何人有任何额外的想法,我有兴趣听到之前我宣布官方“答案” – Schneems 2011-05-11 16:24:54

+0

我不知道你还等什么其他类型的解决方案。一旦这些方法之一需要额外的逻辑,它不再反对“干”原则有一个不同的方法。 – 2011-05-12 01:51:32