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
のメソッドshow
、foo
、およびへのルートのみが必要です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 メソッドがあることを伝えることで自動的にルートを生成させたいと考えましfoo
たbar
。only:
引数) 。
この回答のアドバイスに従い、次のように変更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#foo
reso/foo
foo_reso
No route matches [GET] "/foo_reso"
foo_reso_path
foo_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_reso
withfoo_reso_path
または withを置き換えても違いがないことに注意してください。foo_reso_url
ResoController
私が使用する場所はfoo_reso
コントローラーとビューであるため、問題にはなりません。