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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/128450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 20:41:17  来源:igfitidea点击:

Best Practices for reusing code between controllers in Ruby on Rails

ruby-on-railsruby

提问by Kyle Boon

I have some controller methods I'd like to share. What is the best practice for doing this in ruby on rails? Should I create an abstract class that my controllers extend, or should I create module and add it in to each controller? Below are the controller methods I want to share:

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

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

回答by Ian Terrell

In my opinion, normal OO design principles apply:

在我看来,正常的面向对象设计原则适用:

  • If the code is really a set of utilities that doesn't need access to object state, I would consider putting it in a module to be called separately. For instance, if the code is all mapping utilities, create a module Maps, and access the methods like: Maps::driving_directions.
  • If the code needs state and is used or could be used in every controller, put the code in ApplicationController.
  • If the code needs state and is used in a subset of all controllers that are closely and logically related (i.e. all about maps) then create a base class (class MapController < ApplicationController) and put the shared code there.
  • If the code needs state and is used in a subset of all controllers that are not very closely related, put it in a module and include it in necessary controllers.
  • 如果代码真的是一组不需要访问对象状态的实用程序,我会考虑将它放在一个模块中单独调用。例如,如果代码都是映射实用程序,则创建一个模块Maps,并访问如下方法: Maps::driving_directions
  • 如果代码需要状态并且在每个控制器中使用或可以使用,请将代码放在 ApplicationController 中。
  • 如果代码需要状态并且在所有密切相关且逻辑相关(即所有关于地图)的控制器的子集中使用,则创建一个基类 ( class MapController < ApplicationController) 并将共享代码放在那里。
  • 如果代码需要状态并且在所有不是非常密切相关的控制器的子集中使用,请将其放入模块并将其包含在必要的控制器中。

In your case, the methods need state (params), so the choice depends on the logical relationship between the controllers that need it. In addition:

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

Also:

还:

  • Use partials when possible for repeated code and either place in a common 'partials' directory or include via a specific path.
  • Stick to a RESTful approach when possible (for methods) and if you find yourself creating a lot of non-RESTful methods consider extracting them to their own controller.
  • 尽可能对重复代码使用部分,并放置在公共“部分”目录中或通过特定路径包含。
  • 尽可能坚持使用 RESTful 方法(对于方法),如果您发现自己创建了许多非 RESTful 方法,请考虑将它们提取到自己的控制器中。

回答by Sam G

I know this question was asked 6 years ago. Just want to point out that in Rails 4, there're now Controller Concerns that're a more out of the box solution.

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

回答by danpickett

I actually think a module is the best way to share code amongst controllers. Helpers are good if you want to share code amongst views. Helpers are basically glorified modules, so if you don't need view level access, I suggest placing a module in your lib folder.

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

Once you create the module, you'll have to use the include statement to include it in the desired controllers.

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

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

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

回答by Christoph Schiessl

I agree with the module approach. Create a separate Ruby file in your lib directory and put the module in the new file.

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

The most obvious way would be to add the methods to your ApplicationController, but I am sure you know that already.

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

回答by Shanison

if you want to share codes between controller and helpers, then you should try creating a module in library. You can use @template and @controller for accessing method in controller and helper as well. Check this for more details http://www.shanison.com/?p=305

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

回答by Daniel Bonnell

I found that one effective way to share identical code across controllers is to have one controller inherit from the other (where the code lives). I used this approach to share identical methods defined in my controllers with another set of namespaced controllers.

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

回答by Alan

Another possibility:

另一种可能:

If your common code needs state and you want to share the behavior amongst controllers, you could put it in a plain old ruby class in either your modelor libdirectory. Remember that modelclasses don't have to be persistent even though all ActiveRecord classes are persistent. In other words, it's acceptable to have transient modelclasses.

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