我全都是为了更瘦的模特心态。
我想知道如何去做:
如何识别应该移动到模型的东西(假设你像我一样,你变得很懒,需要重构你的控制器,因为你只是在那里推送代码)
如何编写和构建控制器中新元素的创建。 请参阅以下示例。
示例
我有一个相对凌乱的控制器,用于多元“投票”。我已经很好地清理了它,但我想知道我是否可以更好地改进这个动作:
def up
vote = Vote.new
vote.vote = true
vote.voter = current_user
vote.voteable = Recipe.find params[:id]
vote.save
end
对我而言,这只是有点难看,我可能应该只使用create
而不是新的,但我想知道我是否通过使用非标准动作来驱逐这里的致命路径(关于REST)。
我正在努力将其转换为new
。但我当然希望得到社区的观点。
答案 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,群众投票等)。