2010-01-16 68 views
1

我都是为了更瘦的控制器,更胖的模型心态。Rails:清理丑陋的控制器

我想知道如何去:

  1. 你怎么确定的事情,应该被移动到你的模型(假设你和我一样,你偷懒,需要重构自己的控制器,因为你只是推在那里的代码)

  2. 如何编写和结构控制器中新元素的创建。 请参阅以下示例。

我有一个polymophic “投票” 相对凌乱控制器。我已经清理起来相当不错,但我想知道如果我能改善这个动作好一点:

def up 
vote = Vote.new 
vote.vote = true 
vote.voter = current_user  
vote.voteable = Recipe.find params[:id] 
vote.save 
end 

对我来说只是一个小丑,我可能应该只使用create,而不是新的,但我想知道如果我使用非标准操作(关于REST)在这里驾驶着致命的路径。

我正在把它切换到new现在。但我绝对想得到社区的观点。

回答

2

关键是测试驱动开发。一旦你成为一种习惯,95%的时间都会回答代码放置位置的问题。这是为什么。

单元测试(Rails中的模型测试)是测试代码最简单的地方。模型方法应该是单元测试的“黑盒子”风格 - 这意味着你不关心方法内部的内容,只需要输入X提供输出Y.这也会导致你在你的模型中编写更多更小的方法,而不是非常大的方法。测试越简单,越好 - 而不仅仅是为了测试。更简单的方法更容易被其他代码覆盖,这是Ruby的一大优势。

另一方面,控制器(功能)测试将会发现您更关心里面里面发生了什么动作,因为这些方法不是剪切和干的输入/输出场景。数据库调用发生,会话变量设置等。Shoulda是一个很棒的测试套件,可以为您自动完成大量的工作。

最后,我的建议是看看你最喜欢的插件,看看他们是如何做的。如果您对测试更感兴趣,我有一篇关于restful controller tests in Shoulda的文章可能会让您开始。

+0

优秀的建议。 – 2010-01-17 05:02:32

1

在REST风格的控制器,特别是有很多的动作我有时会造成的before_filter加载对象:

before_filter :load_recipe, :only => %w(show edit update destroy up down) 

private 
def load_recipe 
    @recipe = Recipe.find(params[:id]) 
end 

在你的情况下,我可能会考虑将投票给用户的模式,所以你会碰到这样的:

def up 
    current_user.vote(@recipe) 
end 

然后在你的模型:

class User < ActiveRecord::Base 
    has_many :votes 

    def vote(object) 
    votes.create(:vote => true, :voteable => object) 
    end 
end 

的是因为您可以轻松地单独测试投票行为,并且可以重新使用该投票,如果您还有其他地方可能希望启用投票(如通过其他操作的隐式结果进行投票,通过API进行投票,投票等)。

+0

嗯,感谢问题是它需要保持多态现在。 – 2010-01-17 01:04:27

+0

我不知道你在做什么。我写的和你的一样多形(即不完全是因为配方是明确的)。我的方法没有任何方法可以排除完整的多态性(并且在某些方面它更好地支持它)。 – gtd 2010-01-18 22:10:00