5

Product モデルと ProductsController があるとします。コントローラーにはすべての標準 CRUD メソッドがあり、製品にはあらゆる種類の検証などがあります。

ここに問題があります。複数の形式 (json、html、xml、csv、pdf など) で応答する必要があるカスタムの非常に複雑なアクションがいくつかあります。このビジネス ロジックの理由は、質問の範囲を超えています。これが行われなければならない方法です。また、私は InheritedResources 宝石を使用していますが、質問には関係ないと思います。

例(これは非常に単純化されたモックアプリです-すべての種類のif elseステートメント、ループ、ローカリゼーションなどを削除しました):

class ProductController < InheritedResources::Base
  ....
    def check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order
      @order = Order.new
      @product = Product.find(params[:legacy_alphanumeric_product_number])
      if @product.stock > 5
        @po = LegacyOrder.create_po
        if @po
          if @order.save
            format.html{ render :check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order, flash: {success: "Wow! Input was good!"}}
            format.json{ render status: 400, json: {status: :success, message: "Order created"}}
          else
            format.html{ render :check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order, flash: {error: "Can't create order, some validations failed"}}
            format.json{ render status: 400, json: {status: :error, message: "Problem with order", errors: @order.errors}}
          end
        else
          format.html{ render :check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order, flash: {error: "Can't create order, PO number wasn't generated"}}
          format.json{ render status: 400, json: {status: :error, message: "Problem with po", errors: @po.errors}}
        end  
      else
        respond_to do |format|
          format.html{ render :check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order, flash: {error: "Can't create order, stock is low"}}
          format.json{ render status: 400, json: {status: :error, message: "Problem with product", errors: @product.errors}}
        end
      end  
    end   
  ....
end 

これは、いくつかのアクションの複雑さを示すためのものです。

ここで問題となるのは、そのすべての利点をモデルに移行する必要があるかどうかです。私はコントローラーにあるはずのビジネスロジックを扱っていますが、ファットモデルとシンコントローラーの経験則を守ろうとすると、それを移動する必要があるように思えます。 ?

おまけ Q: REST インターフェースではなく、コード内でその機能の一部を使用する必要があるユース ケースに出くわしています。IE rake タスクの実行中に check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order を使用する必要があります。在庫不足に基づいて、または電子メールイベントなどからいくつかの注文を生成するように。ここで説明されているオプションを使用できますが、Rails のコンソールからコントローラー/ビューメソッドを呼び出すにはどうすればよいですか? 、このアクションをモデルの一部として持つと、簡単になりますよね?

では、このような場合、Rails のベスト プラクティスはどのような行動を取るのでしょうか?

4

3 に答える 3

2

Draper gem ( https://github.com/drapergem/draper ) を見てみましょう。これは、何を表示または応答するかについてロジックを配置するのに最適な場所である素敵なデコレーター スタイルのラッパーを提供します。モデルまたはコントローラーに属さないという@mohamadに同意します。サービス オブジェクトを使用するか、Draper を使用してプレゼンテーション固有のロジック メソッドを作成することは間違いなく良い方法です。

于 2013-06-03T23:56:43.347 に答える
0

ご覧のとおり、問題はコードをコントローラーからモデルに移動することではなく、コントローラーのメソッドをリファクタリングすることです

check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order

例として

format.html{ render :check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order, flash: {success: "Wow! Input was good!"}}
format.html{ render :check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order, flash: {error: "Can't create order, stock is low"}}

フラッシュメッセージ以外は同じです。したがって、次のようなフラッシュ メッセージのみを生成する可能性があります。

#conditions for the flash message
format.html{ render :check_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_order, flash: msg}

したがって、コードをリファクタリングしてみてください。個人的には、xml、json を同じコントローラーに出力しません。のようなWeb APIメソッドを持つことcheck_stock_using_legacy_identifier_and_create_a_unique_po_number_and_place_an_orderは私にとって見栄えが悪いからです:)

すべての Web API メソッドを次のような名前空間に移動します。

<url>/api/ etc

そして、良いテスト カバレッジがあれば、先に進んでコードをリファクタリングすることができます。

于 2013-06-04T00:01:45.263 に答える