65

ユーザーのセッションに接続されている注文を 1 つだけ操作してもらいたい。だから私は注文のために単一のリソースを設定しました

ルート.rb:

resource :order

ビュー/注文/new.html.erb:

<%= form_for @order do |f| %>
   ...
<% end %>

しかし、新しい注文ページを開くと、エラーが発生します。

undefined method `orders_path`

に設定できることはわかっています:url => order_pathform_for、この衝突を解決する本当の方法は何ですか?

4

2 に答える 2

61

残念ながら、これはバグです。あなたが言及したようにURLを設定する必要があります。

= form_for @order, :url => order_path do |f|

これは、永続化されているかどうかに応じて、createまたはに適切にルーティングされることに注意してください。update@order


アップデート

もう一つの選択肢があります。これをルート構成に追加できます。

resolve("Order") { [:order] }

次に、polymorphic_urlクラス名が「Order」のオブジェクトがメソッドに与えられると、 jskol の answerで説明されているよう[:order]に呼び出す代わりに、url コンポーネントとして使用されます。model_name.route_key

これには、スコープまたは名前空間内で使用できないという制限があります。ルート構成の最上位で名前空間モデルをルーティングできます。

resolve('Shop::Order') { [:shop, :order] }

ただし、余分なコンポーネントを含むルートには影響しないため、

url_for(@order)           # resolves to shop_order_url(@order)
url_for([:admin, @order]) # resolves to admin_shop_orders_url(@order) 
                          #        note plural 'orders' ↑
                          #        also, 'shop' is from module name, not `resolve` in the second case
于 2010-09-17T18:26:03.987 に答える
52

その魔法の道はどこから来るのですか?

多くのトレースが必要でしたが、最終的に url_forがActionDispatch::Routing::PolymorphicRoutespolymorphic_pathで定義されたメソッドを使用してモデルのパスを決定することがわかりました。次の行に沿って何かを呼び出すことにより、最終的にモデルの自動魔法のパスを取得します。polymorphic_path

record.class.model_name.route_key

少し簡略化していますが、基本的にはこれです。配列がある場合 (例: form_for[@order, @item])、各要素に対して上記が呼び出され、結果が で結合され_ます。


model_nameClass のメソッドはActiveRecord::Namingから取得されます。

module ActiveModel
  ...
  module Naming
    ...
    def model_name
      @_model_name ||= begin
        namespace = self.parents.detect do |n|
          n.respond_to?(:use_relative_model_naming?) && 
                                                 n.use_relative_model_naming?
        end
        ActiveModel::Name.new(self, namespace)
      end
    end
  end
end


どうすれば変更できますか?

幸い、 ActiveModel::Nameは route_key を含むすべての値を事前に計算するため、その値をオーバーライドするには、インスタンス変数の値を変更するだけです。

質問の:orderリソースについて:

class Order < ActiveRecord::Base
  model_name.instance_variable_set(:@route_key, 'order')
  ...
end

# new.html.erb
<%= form_for @order do |f| # Works with action="/order" %>
    ...
<% end %>

やってみて!

于 2013-04-26T05:09:25.810 に答える