2011-01-24 13 views
1

カテゴリに2つの異なるモデルが表示されます。私は、「/いくつかのカテゴリ名/一部-fooという名」、 "のようなURLをロードする。これは、正常に動作しますRailsで同じURLフォーマットの異なるコントローラにルーティングするにはどうしたらいいですか?

ActionController::Routing::Routes.draw do |map| 
    map.top_list ':category/:foo', :controller => 'foo', :action => 'show' 
    map.top_list ':category/:bar', :controller => 'bar', :action => 'show' 
end 

:私のroutes.rbをでは、私はこのような何かを持っていると思いますいくつかの-fooという名は、」そうのようなFooControllerによってロードすることができます。

class FooController < ApplicationController 
    def show 
    @foo = Foo.find_by_url! params[:foo] 
    end 
end 

しかし、私はのように、バーを要求しようとすると、 『/いくつかのカテゴリ名/いくつかのバー名』、私が取得します"ActiveRecord :: RecordNotFound in FooController#show"

ActionController::Routing::Routes.draw do |map| 
    map.top_list ':category/:foo', :controller => 'foo', :action => 'show', :requirements => { :name => /^foo-/ } 
    map.top_list ':category/:bar', :controller => 'bar', :action => 'show', :requirements => { :name => /^bar-/ } 
end 

しかし、名前にこの制限を強制的に:私は、このようなルートを定義し、すべてのFooの名前は「foo-」で始まり、すべてのバーの名前は「バー - 」で始まることを要求することにより、この問題を解決することができることを知っていますかなり最適ではありません。私はかもしれない、私のために働くかもしれない以下を見つけた:Different routes but using the same controller for model subclasses in Rails。しかし、私はその例にはあまり慣れていないので、これが私の問題を解決するかどうかはわかりません。私のFooとBarControllerがCategoryControllerから継承しなければならないことも素晴らしいことではありません。

私に起こった1つの考えは、私がFooを検索しようとする可能性があり、失敗した場合はBarControllerにフォールバックすることでした。私はFooControllerでこれを簡単に実行してBarControllerにリダイレクトすることができますが、バーのすべての要求はRailsログにFooController#showとして記録されるため、これは問題ありません。しかし、URLの基本名に基づいてルーティングするものを決定するメソッドを呼び出すようにルートを設定することができれば、必要な動作を得ることができます。例えば

ActionController::Routing::Routes.draw do |map| 
    is_a_foo = Proc.new {|name| Foo.find_by_url! name && true } 

    map.top_list ':category/:foo', :controller => 'foo', :action => 'show', :requirements => { :name => is_a_foo } 
    map.top_list ':category/:bar', :controller => 'bar', :action => 'show' 
end 

bog-standard Rails 2でこれを行う方法はありますか?

+0

次の質問に答えがあった場合は、http:// stackoverflowというこの質問にも答えます。com/questions/5767222/rails-call-another-controller-action-from-a-controller –

答えて

2

は、私は私がこのような経路を書くことができます少しのRailsプラグイン書いてしまった:私は、ソースコードをオープンする許可を得るまで

map.with_options :category => /[-A-Za-z0-9]+/ do |m| 
    # Since both foos and bars can appear under category, we define a route for foo that only matches when 
    # the foo can be found in the database, then fall back to the bar route 
    m.foo ':category/:foo', :controller => 'foo', :action => 'show', :conditions => { 
     :url => { :find_by_url => Foo } 
    } 
    m.bar ':category/:bar', :controller => 'bar', :action => 'show' 
end 

を、私はのための運動としての実装を残していますここでは、読者が、私はそこに着いた方法は次のとおりです。

  1. Monkey-patching Rails: Extending Routes #2
  2. Under the hood: route recognition in Rails
  3. The Complete Guide to Rails Plugins: Part II

できるだけこの回答をgithubリンクで更新します。 :)

0

2つのコントローラに同じルートを使用しているので、これは間違っています。 Railsは気付いた通りに1つだけを選択します。

このようなものを使用してよりよいだろう:あなたは2つのparamsそれぞれの時間を与える

map.top_list ':category/foo/:foo', :controller => 'foo', :action => 'show', :requirements => { :name => is_a_foo } 
map.top_list ':category/bar/:bar', :controller => 'bar', :action => 'show' 

提供ルートでいるので。あなたの名前を違うものにすることは重要ではありません。両方とも一致します。

+0

私は同意します。しかし、その道のりはビジネスの人々によって設定された要件です。 :) –

+0

これらのパスにいくつかの例を挙げて、私は明日の朝仕事で見ていきますので、わかりました。 2つの可能性があります: 1.ちょうど多少調整されるでしょうが、fooと:bar識別子が一意であるコントローラを使用する必要があります。たとえばbefore_filterを使用することができます。 2.識別子が重複する可能性がある場合は、少なくとも1つのパスがわずかに異なる必要があります。 – m4risU

関連する問題