3

コントローラのアクションで参照できる一般的なルートを作成しようとしています。

私は次の行を使用しています:

  match ':action' => 'pages#:action', :as => 'action'

ページコントローラで「foobar」という名前のアクションを考えてみましょう。書けるようになりたい

link_to 'Click Me', pages_foobar_path

ビューで。問題は、Invalid route name: ':action'そのルートを書き込もうとするとエラーが発生することです。

気をつけて、ライン

match ':action' => 'pages#:action'

パラメータがないと:as完全に機能しますが、パスを手動で記述する必要があります。

link_to 'Click Me', '/pages/foobar'

それを回避する方法はありますか?

4

3 に答える 3

5

dynamicが「Rails の起動時に自分のアクションを認識し、ルートを動的に生成する」ことを意味する場合:

それは私がすることではありませんが、リダイレクトや method_missing ランタイム オーバーヘッドなしで、やりたいことを実行します

config/routes.rb

controller_filenames = Dir.new("#{Rails.root}/app/controllers").entries
controller_filenames.each do |filename|
  # you could restrict to only the pages_controller.rb on the next line,
  # and in that case, you could simplify even more (see next example)...
  if filename =~ /_controller\.rb$/
    controller_name = filename.sub(/.rb$/, "")
    controller_route_name = controller_name.sub(/_controller$/, "")
    controller = controller_name.camelize.constantize.new
    controller.action_methods.each do |action|
      # if you don't want the controller name in your path match, just omit it...
      match "#{controller_route_name}/#{action}" => "#{controller_route_name}##{action}", :as => "#{controller_route_name}_#{action}"
    end
  end
end

これを pages_controller.rb ファイルに対してのみ行いたい場合は、次のようにします。

controller_name = "pages_controller"
controller_route_name = "pages"
controller = controller_name.camelize.constantize.new
controller.action_methods.each do |action|
  # I've removed the controller_route_name from the match here...
  match "#{action}" => "#{controller_route_name}##{action}", :as => "#{controller_route_name}_#{action}"
end

ここで、動的が「新しいアクションを動的に生成するたびにルートを生成する」ことを意味する場合:

本当に火遊びができます。既存のアクションのいずれかで、新しいアクションとルートを定義できます。たとえば、次のようにルートを定義できますconfig/routes.rb(ただし、これは任意の既存のルートである可能性があります)。

match '/dynamic_define' => 'application#dynamic_define'

これをメソッド in と組み合わせApplicationControllerます (これも既存のアクションである可能性があります)。

def dynamic_define
  method_name = params[:mname]
  self.class.send(:define_method, method_name) {
    render :text => "output from #{method_name}"
  }
  Rails.application.routes.disable_clear_and_finalize = true
  Rails.application.routes.draw do
    match "/#{method_name}" => "application##{method_name}", :as => "application_#{method_name}"
  end
  render :text => "dynamic_define just created a new action named #{method_name}"
end

ブラウザで次の場所にアクセスできます。

/dynamic_define?mname=my_new_dynamic_action
# browser renders "dynamic_define just created a new action named my_new_dynamic_action"

そして、次の場所にアクセスしてください。

/my_new_dynamic_action
# browser renders "output from my_new_dynamic_action"
于 2012-05-12T18:38:29.943 に答える
2

私はあなたがどこまでも得ることができると思います:

link_to 'Click me', pages_path(:action)

リダイレクトすることによって

match ':action' => 'pages#:action'
match '/pages/:action' => redirect(":action") # pages_path(:action) will match

これは、最初の回答で提案されたアプローチよりもタイピングが少ないですが、どちらかといえば表現力が低いようです。

ビュークラスのmethod_missingをオーバーライドして、pages_ [stuff] _pathをキャッチし、適切な文字列を生成できると思います。

def method_missing(name, *args, &block)
  if name =~ /^pages_[a-z]*_path$/
    "/#{name.to_s.gsub!(/^pages_/,'').gsub!(/_path$/,'')}"
  else
    super
  end
end

私のmethod_missing知識または正規表現機能が不足している場合は、私を許してください-うまくいけば、これは少なくとも方向的に役立つでしょう。

于 2012-05-06T04:46:27.820 に答える
0

そのようにルートを書く場合、それにアクセスする正しい方法は次のとおりです。

link_to 'Click me', action_path(:action => 'foobar')
于 2012-04-20T07:43:46.790 に答える