OO在Rails中的devise:在哪里放东西
我非常喜欢Rails(尽pipe我通常是RESTless),而且我非常喜欢Ruby。 不过,制作大量ActiveRecord子类和巨大控制器的趋势是非常自然的(即使您对每个资源使用控制器)。 如果你要创build更深的对象世界,那么你会在哪里放置类(和模块,我想)? 我在询问有关意见(在助手本身?),控制器和模型。
解放军是好的,我已经find了一些解决scheme,让它在开发环境中重新加载 ,但我想知道是否有更好的方法来做这个东西。 我真的只是担心类越来越大。 另外,发动机又如何呢?
由于Rails以MVC的方式提供结构,因此最终只能使用为您提供的模型,视图和控制器容器。 初学者(甚至一些中级程序员)的典型习惯是将应用程序中的所有逻辑embedded到模型(数据库类),控制器或视图中。
在某些时候,有人指出了“胖模型,瘦控制器”的范例,中间开发者急于从控制器中删除所有东西,并将其投入到模型中,开始成为应用程序逻辑的新垃圾箱。
实际上,瘦控制器是一个好主意,但推论 – 把所有东西都放在模型中,并不是最好的计划。
在Ruby中,为了使事物更加模块化,你有两个很好的select。 一个相当普遍的答案是只使用模块(通常保存在lib
)来存放一组方法,然后将模块包含到适当的类中。 这有助于在您希望在多个类中重用的function类别的情况下,但function仍按名称附加到类的情况。
请记住,当你将一个模块包含到一个类中时,这些方法就会成为这个类的实例方法,所以你最终还是得到一个包含大量方法的类,它们被很好地组织成多个文件。
这种解决scheme在某些情况下可以很好地工作 – 在其他情况下,您将需要考虑在代码中使用非模型,视图或控制器的类。
考虑一个好的方法就是“单一责任原则”,即“单一责任原则”,即一个class级应该负责单个(或less数)的事情。 您的模型负责将应用程序中的数据保存到数据库中。 您的控制器负责接收请求并返回可行的响应。
如果你的概念不适合那些框(持久性,请求/响应pipe理),那么你可能想要考虑如何对这个想法进行build模。 您可以将非模型类存储在app / classes或其他任何地方,并通过执行以下操作将该目录添加到您的加载path中:
config.load_paths << File.join(Rails.root, "app", "classes")
如果您使用的是乘客或JRuby,则可能还需要将path添加到热切的加载path中:
config.eager_load_paths << File.join(Rails.root, "app", "classes")
最重要的是,一旦你发现自己在问这个问题的时候到了一个地步,现在是时候加强你的Rubysorting,并开始build模,这些类不仅仅是Rails默认给你的MVC类。
更新:这个答案适用于Rails 2.x及更高版本。
更新 :关注的使用已被确认为Rails 4中的新默认 。
这真的取决于模块本身的性质。 我通常将控制器/模型扩展放置在应用程序的/关注文件夹中。
# concerns/authentication.rb module Authentication ... end # controllers/application_controller.rb class ApplicationController include Authentication end # concerns/configurable.rb module Configurable ... end class Model include Indexable end # controllers/foo_controller.rb class FooController < ApplicationController include Indexable end # controllers/bar_controller.rb class BarController < ApplicationController include Indexable end
/ lib是我的通用库的首选。 我总是有一个项目名称空间在lib中放置所有应用程序特定的库。
/lib/myapp.rb module MyApp VERSION = ... end /lib/myapp/CacheKey.rb /lib/myapp/somecustomlib.rb
Ruby / Rails核心扩展通常在configuration初始化程序中进行,以便只在Rails boostrap上加载一次库。
/config/initializer/config.rb /config/initializer/core_ext/string.rb /config/initializer/core_ext/array.rb
对于可重用的代码片段,我经常创build(微)插件,以便我可以在其他项目中重用它们。
帮助器文件通常包含帮助器方法,有时还包含帮助器(例如Form Builders)使用对象的类。
这是一个真正的概述。 如果您想获得更多的定制化build议,请提供有关具体示例的更多详细信息。 🙂
制作巨大ActiveRecord子类和巨大控制器的趋势是相当自然的…
“巨大”是一个令人担忧的词… 😉
你的控制器如何变得巨大? 这是你应该看的东西:理想情况下,控制器应该很薄。 凭借经验法则,我build议如果每个控制器方法(操作)的代码数量超过5或6行,那么你的控制器可能太胖了。 是否有可能进入助手function或filter的重复? 是否有业务逻辑可以推入模型?
你的模型如何变得庞大? 你是否应该想方设法减less每class的责任? 有没有可以提取到mixin的任何常见行为? 还是可以委托给帮助类的function领域?
编辑:试图扩大一点,希望不会扭曲任何太糟糕的…
助手:住在app/helpers
,主要用于使视图更简单。 它们或者是特定于控制器的(也可用于该控制器的所有视图)或者通常可用( module ApplicationHelper
中的module ApplicationHelper
)。
filter:假设你在几个动作中有相同的代码行(通常,使用params[:id]
或类似的方式检索对象)。 可以首先将这种重复抽象为一个单独的方法,然后通过在类定义中声明一个filter(比如before_filter :get_object
完全脱离这些操作。 请参阅“ ActionController Rails指南”中的第6部分让声明式编程成为您的朋友。
重构模型更多的是一个宗教的东西。 例如, Bob叔叔的门徒会build议你遵循SOLID的五戒 。 乔尔和杰夫可能会推荐一个更呃实用的方法,尽pipe他们后来看起来似乎稍微调和了一些 。 在类中定义一个或多个方法,在其属性的明确定义的子集上运行是一种尝试识别可能从ActiveRecord派生模型中重构的类的方法。
顺便说一句,Rails模型不一定是ActiveRecord :: Base的子类。 换句话说,模型不一定是桌子的模拟,甚至不涉及任何存储的东西。 更好的是,只要你根据Rails的约定在app/models
命名文件(在类名上调用#underscore来找出Rails将要查找的内容),Rails将会在没有任何require
的情况下find它。
这里有一篇很好的博客文章,讲述重构似乎来自“瘦控制器”哲学的胖模型:
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
基本信息是“不要从胖模型中提取Mixins”,改为使用服务类,作者提供了7种模式