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


82

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

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

1
在这种情况下,是否有不使用application.rb的特定原因?
PJ。

4
只有某些控制器会使用该代码,但不是全部。
凯尔·布​​恩

Answers:


113

我认为,通常的OO设计原则适用:

  • 如果代码实际上是不需要访问对象状态的一组实用程序,那么我会考虑将其放在要单独调用的模块中。举例来说,如果代码是所有测绘事业,创建一个模块Maps,并访问类的方法: Maps::driving_directions
  • 如果代码需要状态并且可以在每个控制器中使用或可以在每个控制器中使用,则将代码放在ApplicationController中。
  • 如果代码需要状态并且被用于与逻辑紧密相关的所有控制器的子集(即所有有关地图的子集中),则创建一个基类(class MapController < ApplicationController)并将共享代码放在此处。
  • 如果代码需要状态并且被使用在所有不是很相关的控制器的子集中,则将其放在模块中并将其包括在必要的控制器中。

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

也:

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

33

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


16

我实际上认为模块是在控制器之间共享代码的最佳方法。如果您想在视图之间共享代码,则助手是很好的选择。助手基本上是美化的模块,因此,如果您不需要视图级别的访问,建议将模块放在lib文件夹中。

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

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


1

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

最明显的方法是将方法添加到ApplicationController中,但是我确定您已经知道这一点。


1

如果要在控制器和助手之间共享代码,则应尝试在库中创建模块。您也可以使用@template和@controller来访问controller和helper中的方法。检查此以获取更多详细信息http://www.shanison.com/?p=305


0

另一种可能性:

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


0

我发现一种在多个控制器之间共享相同代码的有效方法是让一个控制器从另一个继承(代码所在的地方)。我使用这种方法与另一组命名空间控制器共享了在控制器中定义的相同方法。


1
使用继承来共享代码被视为一种代码味道。你应该避免它。请参阅developers.stackexchange.com/a/12446。而是使用模块,关注点甚至服务对象
宇达电通2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.