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
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)
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).
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.
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.
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 :-)