2017-04-03 10 views
1

どのように動作するのか誰にでも分かります。どのようにRailsがActiveRecordインスタンスに使用する名前付きルートヘルパーを決定するのですか?

私はRails 5.0.0.1プロジェクトで作業しています。実用上の理由から、我々は我々はそれに応じてQuestionAnswerモデルを持っている

namespace :survey do 
    resources :questions 
    resources :answers 
end 

のような名前空間のルートを使用しています。

documentationヘルパーlink_toは単にビュー(HAML)単純な書き込みに私の場合を意味する第二パラメータとして以下をActiveRecordのインスタンスを渡すと共に使用することができることを、伝え:

= link_to 'Show question', @question 

名前空間が存在しないにもかかわらず、名前付きヘルパーメソッドquestion_pathの場合は、ルートが名前空間になっていても、これはsurvey_question_pathの代わりになります。ポイントは、私がに、を使用するようにroute helperという名前のActiveRecordインスタンスから決定したいということです。

興味深いのは、質問インスタンスがの質問 _pathのような名前付きルートを持つことをRailsが認識しているということです。

は、私がこれまでのところ考え出した:link_toの2番目のパラメータは、適切な(またはしない)という名前のルートヘルパーを選択するヘルパーメソッドurl_forを、使用しています

  • - しかし、どのように?
  • ActiveRecordインスタンスには、route_key(複数)とsingular_route_keyのような属性を含むmodel_nameというメソッドがあります。これが私が探しているものと何か関係があるかどうか、またはそれを上書きする方法があるかどうかはわかりません。

私は別のビューディレクトリからアクションをレンダリングするためにrender @questionためto_partial_path、またはコントローラの場合はself.controller_pathのようなモデルで上書きするための簡単な方法があったと思ったが、私はそれを見つけることができません。

ご協力いただければ幸いです。 (Active Recordのような)レコードを渡す

の代わりに、ハッシュ:

EDIT

私は(という名前のルートに頼るAPIdockに次の段落につまずいグーグルいくつかのより多くをした後、 optionsパラメータはそのレコードの名前付きルートをトリガーします。ルックアップはクラス名で行われます。したがって、Workshopオブジェクトを渡すと、workshop_pathルートを使用しようとします。 admin_workshop_pathなどのネストされたルートがある場合は、明示的に呼び出す必要があります(url_forがそのルートを推測することは不可能です)。

答えて

2

Railsはモデルのmodel_nameを使用しているため、その方法は無効にしないでください。あなたはsurvey_question_pathに呼び出しにQuestionを有効にする場合は、あなたが定義する必要があり、独自のsurvey_question_path返しquestion_path ...

def question_path(question) 
    survey_question_path(question) 
end 

...あるいは単に完全な方法は、自分で名前を付けてください。

またurl_forに直接渡されるシンボル/モデル、の配列を使用することができます。

ご質問については
= link_to 'Show question', [:survey, @question] 
+0

ええ、ヘルパーとしては、私はそれを考えましたが、アイデアが好きではない...(私の悪い:-))。一方、あなたの2番目の提案は、配列の中で、私の問題THXを解決するようです( 'model_name'に関しては、私はそれを上書きするつもりはなかった、route_key attribええ、私はあなたが正しいと思う...) – Misu

1

  • のlink_toの2番目のパラメータは、ヘルパーメソッドを使用していますurl_for、 は、適切な(またはそうでない)名前付きルートヘルパーを選択しますが、それはどうですか?

あなたがソースを中心に述べた#url_for方法に従えば、我々はActionView :: RoutingUrlForにActionDispatchから、周りにスローされます::ルーティング:: PolymorphicRoutes

(ソース:https://github.com/rails/rails/blob/870dde4710f1492c83233620f343ec414a07a950/actionview/lib/action_view/routing_url_for.rb#L115)。 、ええ(ActionDispatchで

::ルーティング:: PolymorphicRoutes番号のpolymorphic_url方法、それは内部クラスを使用するとHelperMethodBuilder.polymorphic_methodを呼び出し、「record_or_hash_or_array」としてモデルクラスを含むすべての与えられたオプションを(渡します知っている...))。以下の数行

は、このメソッドの宣言に、あなたはもう少し小さな方法を中心にスローされますと、このような方法で終わる:

def self.build(action, type) 
    prefix = action ? "#{action}_" : "" 
    suffix = type 
    if action.to_s == "new" 
    HelperMethodBuilder.singular prefix, suffix 
    else 
    HelperMethodBuilder.plural prefix, suffix 
    end 
end 

def self.singular(prefix, suffix) 
    new(->(name) { name.singular_route_key }, prefix, suffix) 
end 

def self.plural(prefix, suffix) 
    new(->(name) { name.route_key }, prefix, suffix) 
end 

(ソース:https://github.com/rails/rails/blob/3f2b7d60a52ffb2ad2d4fcf889c06b631db1946b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb

あなたが見ることができるように、それが#NEWアクションやないかどうかを決定し、いずれか、順番に、あなたの2つ目の質問にお答えします#singularまたは#plural、電話するよ:

  • ActiveRecordのインスタンスはroute_key(複数)とsingular_route_keyなどの属性が含まれている方法のMODEL_NAMEを、持っている - 私はこれは私が探しています何を行うには何も持っている場合はわからない、またはそれがどのように持っている場合でも、それを上書きする。我々は@key_strategyとして保存されます。この内部クラスの初期化、最初のパラメータであるラムダに、上記を参照できるよう

これらの2つの方法は、割り当てられます。

else 
    builder.handle_model_call(self, options) 

Builderの側のいくつかのメソッドに渡すます:

def handle_model(record) 
    args = [] 

    model = record.to_model 
    named_route = if model.persisted? 
    args << model 
    get_method_for_string model.model_name.singular_route_key 
    else 
    get_method_for_class model 
    end 

    [named_route, args] 
end 

def handle_model_call(target, model) 
    method, args = handle_model model 
    target.send(method, *args) 
end 

private 

def get_method_for_class(klass) 
    name = @key_strategy.call klass.model_name 
    get_method_for_string name 
end 

def get_method_for_string(str) 
    "#{prefix}#{str}_#{suffix}" 
end 

とバック「** ActionView#URLFORで、私はあなたを示した最初のリンクには、このコールを参照してくださいもし私が何かを見逃していなければ、この最後のメソッドはあなたのURLパスを返します。

+0

うわー! Spectacular ...私は同じことを試みました。それは '@ question.model_name.singular_route_key'に到達した方法です。メソッドのジャングルで紛失してしまっただけです(たとえば、少なくとも5つの' url_for'メソッドがあります。どちらがさらに調査すべきか分からなかった...)。私は 'singular_route_key'をオーバーライドする方法があるのか​​どうか疑問に思っていましたが、私はそれを使わないで管理すると思います。とにかくありがとう :-) – Misu

関連する問題