在Ruby on Rails中重用控制器之间代码的最佳实践

时间:2008-09-24 17:16:47

标签: ruby-on-rails ruby

我有一些我想分享的控制器方法。在轨道上的红宝石中执行此操作的最佳做​​法是什么?我应该创建一个我的控制器扩展的抽象类,还是应该创建模块并将其添加到每个控制器?以下是我想要分享的控制器方法:

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

7 个答案:

答案 0 :(得分:111)

在我看来,正常的OO设计原则适用:

  • 如果代码实际上是一组不需要访问对象状态的实用程序,我会考虑将它放在一个单独调用的模块中。例如,如果代码是所有映射实用程序,请创建模块Maps,并访问以下方法:Maps::driving_directions
  • 如果代码需要状态并且已在每个控制器中使用或可以使用,请将代码放在ApplicationController中。
  • 如果代码需要状态并且在所有与密切和逻辑相关的控制器的子集中使用(即所有关于映射),则创建基类(class MapController < ApplicationController)并将共享代码放在那里。
  • 如果代码需要状态并且在所有不是非常密切相关的控制器的子集中使用,请将其放在模块中并将其包含在必要的控制器中。

在您的情况下,方法需要状态(params),因此选择取决于需要它的控制器之间的逻辑关系。 另外:

此外:

  • 在可能的情况下对重复的代码使用partials,并将其放在公共的“partials”目录中或通过特定路径包含。
  • 尽可能坚持RESTful方法(对于方法)如果您发现自己创建了许多非RESTful方法,请考虑将它们提取到自己的控制器。

答案 1 :(得分:32)

我知道这个问题是在6年前被问到的。只是想指出在Rails 4中,现在的控制器问题是一个更开箱即用的解决方案。

答案 2 :(得分:15)

我实际上认为模块是在控制器之间共享代码的最佳方式。如果您想在视图之间共享代码,那么助手是很好的。帮手基本上是美化模块,所以如果你不需要视图级别访问,我建议你在lib文件夹中放置一个模块。

创建模块后,您必须使用include语句将其包含在所需的控制器中。

http://www.rubyist.net/~slagell/ruby/modules.html

答案 3 :(得分:1)

我同意模块方法。在lib目录中创建一个单独的Ruby文件,并将该模块放在新文件中。

最明显的方法是将方法添加到ApplicationController,但我相信你已经知道了。

答案 4 :(得分:1)

如果你想在控制器和助手之间共享代码,那么你应该尝试在库中创建一个模块。您可以使用@template和@controller来访问控制器和帮助器中的方法。 请查看此内容以获取更多详细信息http://www.shanison.com/?p=305

答案 5 :(得分:0)

另一种可能性:

如果您的公共代码需要状态,并且您希望在控制器之间共享行为,则可以将其放在modellib目录中的普通旧ruby类中。请记住,即使所有ActiveRecord类都是持久的,model类也不必是持久的。换句话说,拥有瞬态model类是可以接受的。

答案 6 :(得分:0)

我发现跨控制器共享相同代码的一种有效方法是让一个控制器继承另一个(代码所在的位置)。我使用这种方法在我的控制器中使用另一组命名空间控制器共享相同的方法。