Rails:清理丑陋的控制器

时间:2010-01-16 23:11:56

标签: ruby-on-rails

我全都是为了更瘦的模特心态。

我想知道如何去做:

  1. 如何识别应该移动到模型的东西(假设你像我一样,你变得很懒,需要重构你的控制器,因为你只是在那里推送代码)

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

  3. 示例

    我有一个相对凌乱的控制器,用于多元“投票”。我已经很好地清理了它,但我想知道我是否可以更好地改进这个动作:

    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 个答案:

答案 0 :(得分:2)

关键是测试驱动开发。一旦你习惯了,95%的时间就会回答你在何处放置代码的问题。这就是原因。

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

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

最后,我的建议是查看一些你最喜欢的插件,看看他们是如何做的。如果您对测试更感兴趣,我会发表一篇关于restful controller tests in Shoulda的文章,可能会帮助您入门。

答案 1 :(得分:1)

在RESTful控制器中,特别是在执行大量操作时,我有时会创建一个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,群众投票等)。