Rails 3.1 No route matches controller and action but they exist - ruby-on-rails-3

I'm playing with a test rails app. However I stumbled on a problem I can't resolve.
I've a users controller and in it there's an activate method.
In the routes.rb file I have
match 'activate/:email/:validation_code' => 'users#activate', :as => :activate_user, :via => :get
After that I try to use activate_user_path(#user) but a routing error is raised.
No route matches {:controller=>"users", :action=>"activate", :email=>#<User id: 12, email: "someone#test.test", validation_code: "zbBPLQUsBgPvEJfcjxmXuxFxuJAKEoqQNASkbybihpnmzSbhxdC...", active: false, created_at: "2011-11-10 14:56:23", updated_at: "2011-11-10 14:56:23">}
Running rake routes shows the routing is there:
activate_user GET /activate/:email/:validation_code(.:format) {:controller=>"users", :action=>"activate"}
I tried searching for this problem, but usually this happens when you forget to pass the object that's needed to build the route.
All help is appreciated :)

I would make sure you are actually invoking a GET and not a POST as the method.
If you are submitting a form, it defaults to POST, which would mean you don't have a matching route, the route you listed above only works for GET requests.

Does activate_user_path(:email => #user.email, :validataion_code => #user.validation_code) works for you?
EDIT
I don't know why, but when I've changed:
validation_code to code it works.
match 'activate/:email/:code' => 'users#activate', :as => :activate_user, :via => :get
Probably in rails you can't use var names in routes with underscore, but this has to be verified.

Related

explicit get route is throwing an error

I defined a custom route:
match 'folio/:id' => 'posts#show', :as => :folio, :via => :get
When I run rake routes command I have:
post GET /posts/:id(.:format) posts#show
folio GET /folio/:id(.:format) posts#show
And I put link for this element in my other page: link_to post.title, folio_path ,but when I enter it throws me an routing error:
No route matches {:controller=>"post", :action=>"show"}
Why it fails? When I'm using post#show in normal way it works like a charm, but with my custom route it fails - please help!
You need to specify the post so rails can fill the id part:
link_to post.title, folio_path(post)

Setting Devise omniauth_path_prefix doesn't work

I'm working on a Rails-based API. I recently started attempting to version it. (I'm using the Versionist gem, in case it matters) One version ('v2') uses Devise and Omniauth to authenticate users through Facebook/Twitter.
I want all the routes associated with this version to have the appropriate version prefix (so users/:username/foo becomes v2/users/:username/foo, etc.), but I've already found out that putting devise_for inside the api_version block prevents the Devise helpers (current_user, user_signed_in?, etc.) from working, so it continues to live outside the block:
routes.rb:
devise_for :user, :path => '', :controllers => {:omniauth_callbacks => 'users/omniauth_callbacks'}, :skip => [:registrations, :confirmations, :sessions, :passwords]
api_version(:module => "V2", :path=>"v2") do
resources :authentications, :only => [:update, :destroy]
devise_scope :user do
post 'login' => 'sessions#create', :as => 'user_session'
get 'logout' => 'sessions#destroy'
post 'password' => 'devise/passwords#create'
put 'password' => 'devise/passwords#update'
end
end
Everything seemed great... except the Devise-generated omniauth routes:
rake routes output:
user_omniauth_authorize /auth/:provider(.:format)
user_omniauth_callback /auth/:action/callback(.:format)
Now, some google-fu revealed that there's a devise configuration setting for this, so I added the following to our devise initializer (config/initializers/devise.rb):
Devise.setup do |config|
config.omniauth_path_prefix = 'v2/auth'
end
Now, rake routes produces paths that look sensible:
user_omniauth_authorize /v2/auth/:provider(.:format) v2/users/omniauth_callbacks#passthru {:provider=>/(?!)/}
user_omniauth_callback /v2/auth/:action/callback(.:format) v2/users/omniauth_callbacks#(?-mix:(?!))
However, when I attempt to access this route by calling api.localhost/v2/auth/facebook, I get a routing error:
ActionController::RoutingError (No route matches [GET] "/v2/auth/facebook")
Any idea what's going on here?
You are missing the provider name in the routes so they don't match the facebook part in /v2/auth/facebook. The correct route destination should look something like v2/users/omniauth_callbacks#(?-mix:facebook).
Have you specified the provider in the user model?
devise_for ..., :omniauthable, :omniauth_providers => [:facebook]
For the record, I'm using Rails 3.2 and Devise 3.0 and the altered route seems to work (I haven't gone further yet to see if something else will break).

Rails 3 routes - URL name?

I'm not sure how to change a route's URL. As the :as parameter does something else now than in Rails 2
This only changes the route helpers to faq_path, but the url still goes to /faqs. I want the url to be singular.
resources :faqs, :as => "faq" do
collection { post :sort }
end
Doing a single match (below) won't really be the same
match "/faq" => "faqs#index"
If you want change all the URLs related to the faqs resources you can do the following:
resources :faqs, :path => 'faq'
See docs for further information.

Trying to create a POST request but getting No route matches [GET]

I'm trying to do something similar to Railscasts #255 but I'm getting a No Route error:
In Ryan's routes.rb file:
post "versions/:id/revert" => "versions#revert", :as => "revert_version"
In in the controller where he uses the route, versions_controller.rb
link = view_context.link_to(link_name, revert_version_path(#version.next, :redo => !params[:redo]), :method => :post)
redirect_to :back, :notice => "Undid #{#version.event}. #{link}"
In my routes.rb
post "/approve/:id" => "listings#approve", :as => "listing_approve"
and view where I use my link:
<%= link_to 'Approve Content', listing_approve_path(#listing), :method => :post %>
My tests return to me a ActionController::RoutingError: No route matches [GET] "/approve/1"
If I leave the method as a GET everything works.. Using rails 3.1.0rc5. Any guidance as to what I'm doing wrong here would be very much appreciated..
EDIT: routes.rb file (the last line is set as match right now to work)
RLR::Application.routes.draw do
root :to => "home#index"
devise_for :users, :controllers => { :registrations => "registrations" }
devise_for :users
match '/user' => "layouts#index", :as => :user_root
resources :users, :only => :show
resources :layouts, :only => [:index, :show]
resources :listings
resources :features
resources :orders
match "/preview/:id" => "listings#preview", :as => "listing_preview", :via => "get"
match "/approve/:id" => "listings#approve", :as => "listing_approve"
end
Hmmmm, it looks right to my eye. The test sounds like it is generating a GET instead of a POST though, so it might be a problem with the link_to call. You've got :method => :post there, so it should be fine. http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to seems to indicate that link_to will generate some javascript to make a POST call on click (and that users with javascript disabled will get a normal GET link unless you use :href="#"), so it might be because your test engine isn't running the javascript.
You can fix this by changing it to a button that submits a hidden form, but that might not be the visual representation you want.
It might be a precedence thing - the first matching route definition in routes.rb is used, so if you have a resources route or something like that it may be matching on that first.
I got the same problem in my rails application and I solved it the same way you did by doing a via: :get on the match instead of a via: :post. I think for some reason when you send a request in the format of /something/:id it will automatically assume its a [GET] request and search for a get route. This of course will cause problems in your routes if you have it as a :POST.
If anyone has a better solution or idea as to why you cannot send a post request in the format '/something/:id' let me know please.

Testing non-resource actions in Ruby on Rails

I've added the following in my config/routes.rb file:
match 'login' => 'sessions#new'
match 'logout' => 'sessions#destroy'
match 'auth/:provider/callback' => 'sessions#create'
match 'auth/failure' => 'sessions#new'
match 'sessions/delegate' => 'sessions#delegate'
This allows me to have my own custom login form that authenticates through OmniAuth and an OpenID provider in this case. The routes and the code works well, but I have a problem with writing functional tests for the SessionsController.
Testing the new action works well:
test "show login form when requesting new session" do
get :new
assert_response :success
end
But testing the create action gives me an exception: ActionController::RoutingError: No route matches {:controller=>"sessions", :action=>"create"}
The code is like this:
test "create session adds logged in user" do
request.env['rack.auth'] = {:uid => auths(:one).open_id, :provider => 'open_id'}
post :create
# assert that create action did it's things here
end
I've tried to replace the post with a get but the result is the same.
Why is the one action found, and not the other?
Presumably it's getting confused because you're not supplying the :provider key from the match pattern. You might find it clearer to specify names for these non-resourceful routes, like:
match 'auth/:provider/callback' => 'sessions#create', as: 'callback'
This will allow you to post callback_path(provider: whatever) in your test, I think :-)