0

Railsがデフォルトで定義するものに加えて、特定のリソースへのカスタムルートを定義したいと考えていました。これを行うには、routes.rbファイルの関連部分は次のようになります。

resource :top, only: [:show]
scope module: :top do
  resource :reso, only: [:show]
end

get 'foo_reso' => 'top/reso#foo'
get 'bar_reso' => 'top/reso#bar'

ご覧のとおり、ResoControllerのメソッドshowfoo、およびへのルートのみが必要ですbar。これは、次のように機能しrake routesます。

    reso GET    /reso(.:format)           top/reso#show
foo_reso GET    /foo_reso(.:format)       top/reso#foo
bar_reso GET    /bar_reso(.:format)       top/reso#bar

これは機能します。ルートに移動するアプリケーション内のリンクをクリックするとfoo_reso、呼び出しが発生しResoController#foo、関連付けられたビューが表示されます。

しかし、私はルート定義が少し見苦しいと考え、ルートを明示的に定義する代わりに、Rails にリソースに 2 つの追加の REST メソッドがあることを伝えることで自動的にルートを生成させたいと考えましfoobaronly:引数) 。

この回答のアドバイスに従い、次のように変更routes.rbしました。

resource :top, only: [:show]
scope module: :top do
  resource :reso, only: [:show] do
    member do
      get :foo
      get :bar
    end
  end
end

今、rake routes与えます:

    reso GET    /reso(.:format)           top/reso#show
foo_reso GET    /reso/foo(.:format)       top/reso#foo
bar_reso GET    /reso/bar(.:format)       top/reso#bar

2 つのケースのパスの違いに注意してください。ヘルパー パスと controller#action は同じですが、パスは から/foo_reso(.:format)に変更されてい/reso/foo(.:format)ます。

(私はすべてのリソース名を で数えられないものとして定義しているconfig/initializers/inflections.rbため、名前の自動複数形化は行われません。私のアプリケーションでは、各コントローラがモデルではなく特定の画面に関連付けられているため、複数形はこのアプリでは、REST メソッドは実際にはリソースに対する操作というよりは関数呼び出しに似ているため、標準とは異なるセットが必要になります)。

ここで、アプリケーション内の へのリンクをクリックすると、foo_reso次のような Rails ルーティング エラー ページが表示されます。

No route matches [GET] "/foo_reso"

元のソリューションを使用する以外に、状況を修正するために何ができるかについてのアイデアはありますか?

編集時に追加、2013-07-12:

以下のコメントに記載されているように、 の出力によると、rake routesヘルパー ルートfoo_resoは呼び出したいコントローラーとメソッドに一致し、一致する URL ( ) を URL バーに手動で入力する、意図したとおりに動作します。ただし、アプリケーション内からルートを開こうとすると、 . 同じエラーが発生します。top/reso#fooreso/foofoo_resoNo route matches [GET] "/foo_reso"foo_reso_pathfoo_reso_url

いったい何が問題なのだろうか?Rails のバグではありませんか?

編集時に追加、2013-07-22:

ユースケースをもう少し明確にするために、ユーザーがページの「リセット」ボタンを押すと、コントローラーのresetメソッドが呼び出され、ページの入力と出力がクリアされるという考え方があります。実際の識別子resetを に変更することで、質問を抽象化していfooます。(resoそして、他のいくつかの識別子も「難読化」の結果です。) 一貫性を保つために同じ翻訳を引き続き使用しますが、foo実際にはreset. (bar別のものですが、ルーティングの問題は同じであるため、問題ではありません。)

Thong Kuah と John Hinnegan の質問に答えるために、これが私が を使用する方法foo_reso_pathです。ファイルの関連部分reso_controller:

class Top::ResoController < Top::ResoSuperController

  # GET /reso
  def show
    ...
    @reset_path = "foo_reso"
    ...
  end # show

  # GET /foo_reso
  def foo
    perform_foo_action
    redirect_to reso_path
  end
  ...
end

ファイルの関連部分app/views/top/reso/show.html.erb:

<%= render partial: "top/resosuper_inputs", locals: { the_form_path: reso_path } %>
...
<input type="hidden" id="reset_path" name="reset_path" value="<%= @reset_path %>">

フォームにはパーシャルが含まれており_resosuper_inputs.html.erb、その関連部分は次のとおりです。

<!-- For using the "Reset" button. -->
<%= javascript_include_tag "my_reset_form.js" %>
<%= simple_form_for :filtering_criteria, url: the_form_path, method: :get do |f| %>
  ... inputs elided ...
  <%= f.button :submit, value: "Search" %>
  <%= f.button :submit, type: 'button', value: "Reset"), id: 'reset_button' %>
<% end %>

resosuperは 2 つの異なるリソースのスーパークラスですが、それがケースに影響を与えるとは思いません。とにかく、ここにJavascriptファイルがありますapp/assets/javascripts/my_reset_form.js

$(document).ready(function() {
  /* Hang functionality on the "Reset" button. */
  $('#reset_button').click(function () {
      var reset_path = $('#reset_path').val();
      window.open(reset_path, "_self")
  });
})

それはjQueryにあり、コメントが言うように、「リセット」ボタンは、値が id の非表示の入力変数に格納されているパスを開きますreset_path。その値はTop::ResoController、変数によってフォームに与えられたもの@reset_path、つまり です"foo_reso"

次のように定義foo_resoした場合、これはすべて正常に機能したことに注意してください。routes.rb

get 'foo_reso' => 'top/reso#foo'

また、代入文でfoo_resowithfoo_reso_pathまたは withを置き換えても違いがないことに注意してください。foo_reso_urlResoController

私が使用する場所はfoo_resoコントローラーとビューであるため、問題にはなりません。

4

3 に答える 3

0

OK、問題が見つかりました。一見不可解なバグを掘り下げた後によくあることですが、解決策は非常に簡単でした。私reso_controller.rbは:

クラス Top::ResoController < Top::ResoSuperController

# GET /reso
def show
  ...
  @reset_path = "foo_reso"
  ...
end # show

割り当て行を次のように置き換えました。

  @reset_path = foo_reso_path

引用符なしfoo_reso_pathで。「リセット」ボタンが意図したとおりに機能するようになりました。

要約すると、以下は機能しません

  @reset_path = "foo_reso"
  @reset_path = "foo_reso_path"
  @reset_path = "foo_reso_url"
  @reset_path = foo_reso

そして、以下機能します:

  @reset_path = foo_reso_path
  @reset_path = foo_reso_url

私は今ばかげていると思いませんか。時間の無駄で申し訳ありません。

于 2013-07-22T12:10:44.237 に答える