2

インデックス(製品のリスト)アクションが必要な製品コントローラがあるとします。簡単。ここで、管理者がいて、プロジェクトにパーツを保管しているとします。どちらも商品をリストする必要がありますが、方法が少し異なります (たとえば、店舗のものにはこの商品の編集リンクを含めないでください)。また、異なるレイアウトを使用しています。

これまでのところ、私の考えは、異なる名前空間の下に 2 つの製品コントローラーを配置しapp/controllers/admin/products_controller.rbapp/controllers/store/products_controller.rbそれぞれに独自のビューとレイアウトを持たせることです。しかし、これは WET コードにつながる可能性があると思います。または、他のコントローラー ビューへの参照 (imo はモジュール性を壊すため、避ける必要があります)。

したがって、実際の質問: 上記を達成するためのより DRY (または実際には適切な) 方法はありますか?

タイトルが実際に質問を反映しているかどうかはわかりません。しかし一方で、もしそうなら、私はおそらく答えをググることができた.

EDIT 3.1 以降、Rails はテンプレートの継承をサポートしています。

4

4 に答える 4

2

管理セクションとストア セクションの間で製品を表示する方法が、管理リンク (作成、編集、破棄) を除いて一定である場合は、製品のパーシャルを作成するのが最も簡単だと思います。ユーザーが管理者であるかどうかを判断する方法があると思います (以下では簡単にするために、単に admin? を使用します)。パーシャル内では、次のようなことを行います...

<div class="product">
    <div class="productheader">
        <%=h product.title %>
    </div>
    <div class="productdescription>
        <%=h product.description %>
    </div>
    <% if admin? %>
    <div class="productadmin">
        <%= link_to "Delete", destroy_product_url %>
        <%= link_to "Edit", edit_product_url %>
    </div>
    <% end %>
</div>

このパーシャルには _product.html.erb という名前を付けてください (アンダースコアは、テンプレートがパーシャルであることをレールに伝えます)。アプリケーションの app/views ディレクトリに shared というフォルダーを作成し、そこにパーシャルを保存します。

このパーシャルを他のビューでレンダリングするには、単純に render メソッドを呼び出して、パーシャル パラメーターを渡します。

単一の製品:

<%= render(:partial => "shared/product", :object => @a_product) %>

複数の製品:

<%= render(:partial => "shared/product", :collection => @products) %>

layout パラメーターを追加することで、パーシャルにレイアウトを適用できます。部分的なレイアウトにはアンダースコアをプレフィックスとして付ける必要がありますが、コントローラーに関連付けられた app/views ディレクトリに保存する必要があります。

<%= render(:partial => "shared/product", :object => @a_product, :layout => "somelayout" %>
于 2009-04-26T12:30:54.110 に答える
1

私が採用しているアプローチは、製品用のコントローラーを 1 つ用意し、そこにコードを追加して、ユーザーが果たす役割を検出し、その役割に基づいてビュー データを条件付きで設定することです。これには、実際のモデル データと、表示するインターフェイスのビットを決定するためにビューのみが使用するデータの両方が含まれます。ビュー自体には、役割ベースのデータに作用し、特定の役割に関連するビットのみをレンダリングできる少量のコードが含まれています。これは、ビューに小さなビジネス ロジックを挿入するか、コントローラーに小さな表示ロジックを挿入するかのいずれかであると主張する人もいるかもしれません。これらの引数にはある程度の有効性があります。ただし、実際には原則間のバランスをとる行為であることがわかり、MVC の純度よりも DRY の価値を好みます。

于 2009-04-26T12:33:16.723 に答える
0

ある種のビューの継承があった場合のみ...すべてのビューを提供する必要なしにコントローラーをサブクラス化できるようにします。良いことは、このパッチがあることです。悪いことは、それがかなり長い間コアに到達できないことです。

それを私のレール2.2に適用した後、私は元の質問に対して次の答えを得ることができました。

サブクラス化コントローラー

ProductControllerは双子に恵まれています:

class Products::AdminController < ProductsController
  layout 'admin'
  before_filter :authenticate
end

class Products::StoreController < ProductsController
  layout 'store'
  before_filter :find_cart
end

それぞれが独自の初期化部分を持っているので、これ自体は非常に見栄えがします。

ルートの変更

  map.resources :products, :controller => 'products/admin', :path_prefix => 'admin',
    :name_prefix => 'admin_'
  map.resources :products, :controller => 'products/store', :path_prefix => 'store',
    :only => [:show, :index], :name_prefix => 'store_'

簡単なルートではありません、defo。しかし、ねえ、この時点以降、ProductControllerビューとパーシャルですべてが正常に機能します(パスヘルパーが固定されていると仮定します)。

共有ビューの変更

各サブクラスコントローラーには、独自のバージョンのindex.html.erbがあります。他のすべては基本クラスで共有されます。

共有テンプレートのパスヘルパーについて話します。かつては

<% form_for @product ... %>

になります

<% form_for [controller_name, @product] ... %>

のように薄くなります

<%= link_to products_path %>

に変わる

<%= link_to send("#{controller_name}_products_path") %>

それがすべての価値があるかどうかはわかりませんが、それは方法です。このパッチをすぐにレールに含める計画があるのはなぜか誰もが知っていますか?

于 2009-05-08T22:46:25.410 に答える
0

Model-View-Controller Pattern について説明しています。このパターンでは、モデルのビューとコントローラーが直交して変化する可能性があります (または、実装方法に応じて、多かれ少なかれ直交します)。

基本的には、編集できるビューとできないビューがあります。繰り返しになりますが、実装によっては、編集可能なビュー編集不可能なビューから派生する場合があります。いずれの場合も、コントローラーまたは上位レベルのコードのいずれかが、条件付きで適切なビューを選択します。

于 2009-04-26T12:29:43.817 に答える