No route matches even though defined in rails 3.2 - ruby-on-rails

I am trying to use url_for in mailer view for a defined route:
<%= url_for(
:controller => 'scribe_requests',
:action => 'accept',
:id => #match.acceptance_token,
:only_path => false) %>
I have defined the route in my routes.rb:
resources :scribe_requests do
member do
match 'accept' => 'scribe_requests#accept', :as => :accept
end
end
And my controller:
class ScribeRequestsController < ApplicationController
respond_to :html
def accept
..
end
..
end
I am not sure what is going wrong here? My delayed job is failing with the exception
"{No route matches {:controller=>"scribe_requests", :action=>"accept",
:id=>"nv4Nl8wWXLX2zFDm3s3t7w"}
/home/syed/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.2.5/lib/action_dispatch/routing/route_set.rb:532:in
raise_routing_error'
/home/syed/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.2.5/lib/action_dispatch/routing/route_set.rb:528:in
rescue in generate'
/home/syed/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.2.5/lib/action_dispatch/routing/route_set.rb:520:in
generate'
/home/syed/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.2.5/lib/action_dispatch/routing/route_set.rb:561:in
generate'
/home/syed/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.2.5/lib/action_dispatch/routing/route_set.rb:586:in
url_for'
/home/syed/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.2.5/lib/action_dispatch/routing/url_for.rb:148:in
url_for'
/home/syed/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.2.5/lib/action_view/helpers/url_helper.rb:107:in url_for'
/home/syed/work/projects/mapunity/retina-india/app/views/notifier/scribe_service_needed_email.html.erb:47:in
_app_views_notifier_scribe_service_needed_email_html_erb___981003510_106966530'
/home/syed/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.2.5/lib/action_view/template.rb:145:in
`block in render'

Had to add :via option to the route definition and it worked. Weirdly, I had done that with no affect. May be some caching issue. So after the change, my route definition became,
resources :scribe_requests do
member do
match 'accept' => 'scribe_requests#accept', :via => :get, :as => :accept
end
end
Test run:
ruby-1.9.2-p0 > app.url_for :controller => 'scribe_requests', :action => 'accept', :id => 'test'
=> "http://www.example.com/scribe_requests/test/accept"
Thanks for the help.

Related

rspec for a create route for a resource

I have this spec:
specify { expect(:post => admin_featured_path()).to route_to(:controller => 'admin/featured', :action => 'create')}
I cant' make it pass however it seems logical that the post to the route should be routed to the create action...
This is my route file:
namespace :admin do
resources :featured, only: [:index, :update, :destroy, :create]
end
This is the failure message:
1) Featured routes
Failure/Error: specify { expect(:post => admin_featured_path()).to route_to(:controller => 'admin/featured', :action => 'create')}
ActionController::UrlGenerationError:
No route matches {:action=>"update", :controller=>"admin/featured"} missing required keys: [:id]
# ./spec/routing/featured_spec.rb:7:in `block (2 levels) in <top (required)>'
This should work (untested):
page = post admin_featured_path
expect(page).to route_to(:controller => 'admin/featured', :action => 'create')
{:post => admin_featured_path}.should route_to(:controller => 'admin/featured', :action => 'create')
or
{:post => "admin/featured"}.should route_to(:controller => "admin/featured", :action => 'create')

Rails route that allows POST to a few endpoints and all methods to the rest?

I have a Rails controller with about 60+ actions. I need to change it to allow only POST requests on about 20 actions and any request method for the rest of them.
Is there a way to do this so I don't have to manually specify ever route that is allowed for all routes?
This is what I have so far (and works):
post_regex = /first_route|second_route/
all_routes_regex = /third_route|fourth_route/
map.connect '/myroute/:id/:action', :controller => 'my_controller', :constraints => {:action => post_regex }, :conditions => { :method => :post }
map.connect '/myroute/:id/:action', :controller => 'my_controller', :constraints => {:action => all_routes_regex }
I tried creating something like this but it would just cause a RoutingError.
post_regex = /first_route|second_route/
class AllRoutesConstraint
def self.matches?(request)
(request.query_parameters[:action] !~ post_regex)
end
end
map.connect '/myroute/:id/:action', :controller => 'my_controller', :constraints => {:action => post_regex }, :conditions => { :method => :post }
map.connect '/myroute/:id/:action', :controller => 'my_controller', :constraints => {:action => AllRoutesConstraint }
If you are willing to do it in the controller instead of in routes.rb, it should be pretty straightforward. Let all request types through in the routes file:
# in config/routes.rb
map.connect '/myroute/:id/:action', :controller => 'my_controller'
And then, filter for POST-only actions in the controller.
# in app/controllers/my_controller.rb
POST_ONLY_ACTIONS = [:first_route, :second_route]
before_filter :must_be_post, :only => POST_ONLY_ACTIONS
# your actions...
protected
def must_be_post
unless request.method == "POST"
raise ActionController::MethodNotAllowed.new("Only post requests are allowed.")
end
end
This gets you the same error and error message that Rails would generate for you if you set the method in routes.rb.
The drawback is that your routes.rb file is no longer the single authoritative source on exactly what requests are permissible. But since you were trying to remove some of that information (the list of non-POST requests) from the routes file anyway, you might find the tradeoff acceptable.

how url_for can check constraints from my routes.rb

I try define some translate routes on my rails application. The route change with the subdomain define. So I want this result :
describe "url_for" do
context 'with en' do
it 'brand translate' do
url_for(
:controller => 'boats',
:action => 'index',
:subdomain => :en,
:brand => 'hello',
:only_path => true
).should == '/yacht-charter/brand-hello'
end
end
context 'with fr' do
it 'brand translate' do
url_for(
:controller => 'boats',
:action => 'index',
:subdomain => :fr,
:brand => 'hello',
:only_path => true
).should == '/location-bateau/marque-hello'
end
end
end
Like you can see the only change between both url_for params is the subdomain. I try :
constraints => :subdomain => :en do
match '/yacht-charter/brand-:brand' => 'boats#index', :as => 'en_brand_search'
end
constraints :subdomain => :fr do
match '/location-bateau/marque-:brand' => 'boats#index', :as => 'fr_brand_search'
end
But all the time it's the first route define it use. the second is never define.
How Can i do that. It's a rails bug or not ?
Not sure about it being a rails bug or not, but have a look at https://github.com/francesc/rails-translate-routes it works well and may help achieving this.

How do I update routes from Rails 2 to Rails 3?

Here are some routes I have in Rails 2 and want to upgrade to Rails 3:
map.callback "/auth/:provider/callback", :controller => "authorizations", :action => "create" #omniauth
map.failure "/auth/failure", :controller => "authorizations", :action => "failure" #omniauth
map.signup 'signup', :controller => 'users', :action => 'new'
map.signin 'signin', :controller => 'user_sessions', :action => 'new'
map.signout 'signout', :controller => 'user_sessions', :action => 'destroy'
match "/auth/:provider/callback" => "authorizations#create", :as => :callback
match "/auth/failure" => "authorizations#failure", :as => :failure
match "signup" => "users#new", :as => :signup
match "signin" => "user_sessions#new", :as => :signin
match "signout" => "user_sessions#destroy", :as => :signout
That should get you going.
I would definitely checkout the screencast that apneadiving mentioned as well as Rails' take on routes.
Take a look at the rails_upgrade plugin at https://github.com/rails/rails_upgrade and its rake rails:upgrade:routes.
script/plugin install git://github.com/rails/rails_upgrade.git
rake rails:upgrade:routes
This will take your current routes file and rewrites it using the Rails 3 syntax. Copy the console output and look for any potential optimizations after you've read through the documentation in some of the other answers.
This should answer and make you learn:
http://railscasts.com/episodes/203-routing-in-rails-3
You may also find lots of great information at the Rails Routing from the Outside In.

will_paginate route only works on page > 1

I have the following routes defined:
map.resources :categories, :has_many => :downloads
map.resources :downloads, :member => {:go => :get}, :collection => {:tag => :get}
map.connect '/downlods/page/:page', :controller => 'downloads', :action => 'index'
map.connect '/categories/:category_id/downloads/page/:page', :controller => 'downloads', :action => 'index'
For some reason, the first page that the will_paginate helper is called on causes links with ?page=2 to be rendered, while subsequent pages have links with /downloads/page/2. Do you know what might be causing this?
If you simply declare a route with map.connect, it can be hit and miss as to how it's routed if you do something like:
link_to("Next", :page => 2)
What you might want to do is name the route and then use it that way:
map.downloads_paginated '/downloads/page/:page', :controller => 'downloads', :action => 'index'
Then you use the route by name:
link_to("Next", downloads_paginated_path(2))
These are much more reliable.
As a note, you have '/downlods' in your path instead of '/downloads' but I'm not sure that'd be causing the trouble described.

Resources