Ruby on Rails中控制器之间重用代码的最佳实践
我想分享一些控制器方法。 在轨道上做ruby的最佳做法是什么? 我应该创build一个抽象类,我的控制器扩展,或者我应该创build模块,并将其添加到每个控制器? 以下是我想要分享的控制器方法:
def driving_directions @address_to = params[:address_to] @address_from = params[:address_from] @map_center = params[:map_center_start] # if we were not given a center point to start our map on # let's create one. if !@map_center && @address_to @map_center = GeoKit::Geocoders::MultiGeocoder.geocode(@address_to).ll elsif !@map_center && @address_from @map_center = GeoKit::Geocoders::MultiGeocoder.geocode(@address_from).ll end end def printer_friendly starting_point = params[:starting_point].split(',').collect{|e|e.to_f} ne = params[:ne].split(',').collect{|e|e.to_f} sw = params[:sw].split(',').collect{|e|e.to_f} size = params[:size].split(',').collect{|e|e.to_f} address = params[:address] @markers = retrieve_points(ne,sw,size,false) @map = initialize_map([[sw[0],sw[1]],[ne[0],ne[1]]],[starting_point[0],starting_point[1]],false,@markers,true) @address_string = address end
在我看来,正常的面向对象devise原则适用于:
- 如果代码实际上是一组不需要访问对象状态的实用程序,我会考虑将它放在一个模块中,以便单独调用。 例如,如果代码是所有映射工具,则创build一个模块
Maps
,然后访问诸如Maps::driving_directions
类的方法。 - 如果代码需要状态并在每个控制器中使用或可以使用,请将代码放在ApplicationController中。
- 如果代码需要状态,并在所有控制器的子集中使用,那么所有控制器都是紧密相关的(即所有关于地图),然后创build一个基类(
class MapController < ApplicationController
)并将共享代码放在那里。 - 如果代码需要状态,并且在所有不太密切相关的控制器的子集中使用,则将其放入模块中,并将其包含在必要的控制器中。
在你的情况下,方法需要状态( params
),所以select取决于需要它的控制器之间的逻辑关系。 此外:
也:
- 在可能的情况下使用partials重复代码,并将其放置在常见的“partials”目录中或通过特定path包含。
- 尽可能地坚持一种REST风格的方法(对于方法),如果你发现自己创build了很多非REST风格的方法,就考虑把它们提取到自己的控制器中。
我知道这个问题是在6年前问的。 只是想指出,在Rails 4中,现在有了Controller Concerns,这是一个更加开箱即用的解决scheme。
实际上,我认为模块是在控制器之间共享代码的最佳方式。 如果你想在视图中分享代码,助手是很好的。 助手基本上是荣耀的模块,所以如果你不需要视图级别的访问,我build议在你的lib文件夹中放置一个模块。
一旦创build了模块,就必须使用include语句将其包含在所需的控制器中。
我同意模块方法。 在你的lib目录中创build一个单独的Ruby文件,并将模块放入新文件中。
最明显的方法是将方法添加到您的ApplicationController,但我相信你已经知道了。
如果你想在控制器和助手之间共享代码,那么你应该尝试在库中创build一个模块。 您可以使用@template和@controller来访问controller和helper中的方法。 检查这个更多的细节http://www.shanison.com/?p=305
另一种可能性
如果你的通用代码需要状态,并且你想在控制器之间共享行为,你可以把它放在一个普通的ruby类中,在你的model
或lib
目录中。 请记住,即使所有的ActiveRecord类都是持久的, model
类也不一定是持久的。 换句话说,有瞬态model
类是可以接受的。
我发现跨控制器共享相同代码的一种有效方法是让一个控制器从另一个控制器(代码所在的地方)inheritance。 我使用这种方法与另一组命名空间控制器共享我的控制器中定义的相同的方法。