Ruby onRailsのコントローラー間でコードを再利用するためのベストプラクティス


82

共有したいコントローラーメソッドがいくつかあります。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

1
この場合、application.rbを使用しない特別な理由はありますか?
PJ。

4
一部のコントローラーのみがコードを使用しますが、すべてではありません。
カイルブーン

回答:


113

私の意見では、通常のオブジェクト指向設計の原則が適用されます。

  • コードが実際にオブジェクトの状態にアクセスする必要のないユーティリティのセットである場合は、個別に呼び出されるモジュールにコードを配置することを検討します。たとえば、コードがすべてマッピングユーティリティである場合は、モジュールを作成し、次のMapsようなメソッドにアクセスします Maps::driving_directions
  • コードに状態が必要であり、すべてのコントローラーで使用されているか、使用できる場合は、コードをApplicationControllerに配置します。
  • コードに状態が必要であり、密接かつ論理的に関連するすべてのコントローラーのサブセット(つまり、すべてマップに関するもの)で使用される場合は、基本クラス(class MapController < ApplicationController)を作成し、そこに共有コードを配置します。
  • コードに状態が必要で、あまり密接に関連していないすべてのコントローラーのサブセットで使用されている場合は、コードをモジュールに入れて、必要なコントローラーに含めます。

あなたの場合、メソッドには状態(params)が必要なので、選択はそれを必要とするコントローラー間の論理関係によって異なります。加えて:

また:

  • 繰り返しコードに可能な場合はパーシャルを使用し、共通の「パーシャル」ディレクトリに配置するか、特定のパスを介してインクルードします。
  • 可能な場合は(メソッドの場合)RESTfulアプローチに固執し、RESTful以外のメソッドを多数作成していることに気付いた場合は、それらを独自のコントローラーに抽出することを検討してください。

33

私はこの質問が6年前に尋ねられたことを知っています。Rails 4には、すぐに使えるソリューションであるControllerConcernsがあることを指摘したいと思います。


16

私は実際、モジュールがコントローラー間でコードを共有するための最良の方法だと思います。ビュー間でコードを共有したい場合は、ヘルパーが適しています。ヘルパーは基本的に栄光のモジュールであるため、ビューレベルのアクセスが必要ない場合は、モジュールをlibフォルダーに配置することをお勧めします。

モジュールを作成したら、includeステートメントを使用して、目的のコントローラーにモジュールを含める必要があります。

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


1

モジュールアプローチに同意します。libディレクトリに別のRubyファイルを作成し、モジュールを新しいファイルに配置します。

最も明白な方法は、ApplicationControllerにメソッドを追加することですが、それはすでにご存知だと思います。


1

コントローラとヘルパーの間でコードを共有したい場合は、ライブラリにモジュールを作成してみてください。@templateと@controllerを使用して、コントローラーとヘルパーのメソッドにアクセスすることもできます。詳細については、こちらを確認してくださいhttp://www.shanison.com/?p=305


0

別の可能性:

共通コードに状態が必要で、コントローラー間で動作を共有したい場合は、modelまたはlibディレクトリのいずれかのプレーンな古いrubyクラスにコードを配置できます。modelすべてのActiveRecordクラスが永続的であっても、クラスは永続的である必要はないことに注意してください。言い換えれば、一時的なmodelクラスを持つことは許容されます。


0

コントローラー間で同一のコードを共有する効果的な方法の1つは、一方のコントローラーをもう一方のコントローラー(コードが存在する場所)から継承させることです。このアプローチを使用して、コントローラーで定義された同一のメソッドを、名前空間付きコントローラーの別のセットと共有しました。


1
継承を使用してコードを共有することは、コードの臭いと見なされます。あなたはそれを避けるべきです。Programmers.stackexchange.com/a/12446を参照してください。代わりに、モジュール、懸念事項、さらにはサービスオブジェクトを使用してください。
mio
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.