Using generated paths with resources in Rails - ruby-on-rails-3

I have following routes defined:
CyberTrackRails3::Application.routes.draw do
scope "(:locale)", :locale => /en|de|nl/ do
resources :login do
get 'index', on: :collection
get 'check', on: :collection
end
end
end
Now, url_for(:controller => 'login', :action => 'check'), gives me the correct url, en/login/check.
Using login_check_path however doesn't work. How do I make this work?
I've tried replacing get 'index', on: :collection with match 'check' => 'check' but that doesn't work. Neither does match 'check' => 'login#check'.

since you're adding an action to a resource, i think the automatically generated name is going to be reversed, ie 'check_logins_path' (see adding-more-restful-actions)
do you need login_check_path specifically? if so, you should be able to define the path outside of the resources :login block, ie
match '/login/check' => 'login#check', :via => :get, :as => 'login_check'
and like Fivell suggested, rake routes will show you the automatically generated name for a route.

Related

rails 3 absolute link to generated url

I am looking into generating urls which look like https://mywebsite.com/user/check_email_confirmation/46cee41bc2044104aff8cf7746687ea8
for the famous "please click this link to confirm your email".
So I have a route which I intend to use for this in my routes.rb:
resources :user do
collection do
get 'check_email_confirmation/:generated_url', :to => 'user#check_email_confirmation'
end
end
Now, my trouble is to generate the full address above. I cah generate the SHA (46cee41bc2044104aff8cf7746687ea8) part, but how do I write the "https://mywebsite.com/user/check_email_confirmation/" part in my view?
Added view's code:
<p>Please click <%= url_for(:action => 'check_email_confirmation', :controller => 'user', :only_path => false, :id => #confirmation_url) %> to confirm your e-mail address.</p>
Replace id: with generated_url:.
You could also simplify the url_foring with naming the route by as: in routes
get 'check_email_confirmation/:generated_url', to: 'user#check_email_confirmation', as: :confirmation
More on this at http://viget.com/extend/rails-named-routes-path-vs-url
get "check_email_confirmation/:id" => "users#check_email_confirmation", :as => "check_email_confirmation"

Is a route like `"controller#action"` not the same as `:controller => 'controller'` and `:action => 'action'`?

I have a Rails 3.1 app where I just got some weird behavior.
I had two routes declared as follows:
# OLD METHOD
get 'accept_terms', :to => "users_terms#show"
put 'accept_terms', :to => "users_terms#accept'"
Running rake routes included the following:
# accept_terms
# GET /accept_terms(.:format) {:action=>"show", :controller=>"users_terms"}
# PUT /accept_terms(.:format) {:action=>"accept'", :controller=>"users_terms"}
The GET worked fine, but the PUT produced this error:
AbstractController::ActionNotFound (The action 'accept'' could not be found for UsersTermsController):
I confirmed that the action did exist on that controller.
While tinkering around with the problem, I changed the route declarations to:
get 'accept_terms', :controller => 'users_terms', :action => 'show'
put 'accept_terms', :controller => 'users_terms', :action => 'accept'
Running rake routes produced:
# accept_terms
# GET /accept_terms(.:format) {:controller=>"users_terms", :action=>"show"}
# PUT /accept_terms(.:format) {:controller=>"users_terms", :action=>"accept"}
With this, both GET and PUT worked fine.
Is :to => "controller#action not the same as :controller => 'controllerName', :action => 'actionName'?
The only difference I see in the produced routes is the order of :action and :controller...
In the old method you end the users_terms#accept with both a single quote and a double quote.

Routes problem with I18n_routing gem

I'm on Rails 3 and on my 2nd Rails project (i.e. I'm a newbie). I am making a website with several locales, at the moment Swedish and US. I am using the I18n_routing gem to create localized url:s. I am also using the friendly_id gem to create better urls.
My problem: I cannot get my nested urls to be translated. They remain as the default-urls.
This is my routes.rb:
localized(I18n.available_locales, :verbose => true) do
resources :calculation_types, :only => [:show], :path => '' do
resources :calculations, :only => [:index, :show], :path => '' do
member do
put 'calculate_it'
get 'calculate_it', :redirect_me => true
get 'link'
end
end
end
end
localized(I18n.available_locales, :verbose => true) do
match 'searchresults' => 'home#search-results', :as => :searchresults
match 'about' => 'home#about', :as => :about
match 'advertise' => 'home#advertise', :as => :advertise
match 'terms' => 'home#terms', :as => :terms
match 'calculator' => 'home#calculator', :as => :calculator
match 'feedback' => 'home#feedback', :as => :feedback
end
This is a sample (cut) of my locale (for Swedish):
se:
named_routes_path:
about: 'om'
advertise: 'annonsera'
calculator: 'kalkylator'
feedback: 'feedback'
searchresults: 'sokresultat'
terms: 'anvandaranvisning'
resources:
accumulated-passive-income: "vardet-av-din-passiva-inkomst"
all-about-a-date: "allt-om-ett-datum"
area: "area"
average-speed: "genomsnittshastighet"
birthday-in-days: "fodelsedag-i-dagar"
These are some facts of the case:
The resources-translations include both "calculation_types" and "calculations".
I have tried several set-ups in the translation file.
The SECOND routing WORKS, the one with the "match", they also appear when I do rake routes.
I get no error messages. Everything works fine.
I am using friendly_id as the url-words. An example of a url could be http://local.domain.com:3000/diet/bmi where "diet" is calculation_type.friendly_id and bmi is calculation.friendly_id
I want help with:
- Why do the nested routes not show up as routes? Why are they not being created?
- How do I get this to work?
Do you need any more info to help me?
It seems like it is not a matter of I18n_routing after all since the words that should be translated are actually friendly_id:s. So, disregard the I18n_routing part of this problem and focus on the friendly_id-translation...

Testing Routes with Rspec in Rails 3

I have a form that is suppose to be a POST to CREATE action but it is doing a POST to INDEX action. So i then decided to test my routes with rspec. In my Example i have my test as follows.
it "should recognize a specific invoices#create route" do
assert_routing("/invoices", {:controller => "invoices", :action => "create"})
end
but when i run the test its coming up with this error.
1) InvoicesController on get to :index should recognize a specific invoices#create route
Failure/Error: assert_routing("/invoices", {:controller => "invoices", :action => "create"})
The recognized options <{"action"=>"index", "controller"=>"invoices"}> did not match <{"controller"=>"invoices", "action"=>"create"}>, difference: <{"action"=>"create"}>.
Expected block to return true value.
So im trying to figure out why my form is doing a POST on INDEX and why my test thinks im doing an index route. I have tried inserting :method => :post in the test but it doesnt seem to work.
Have you tried this?:
assert_routing({ :path => "invoices", :method => :post },
{ :controller => "invoices", :action => "create" })

Rails 3 routing

Ok, I'm relatively new to rails and am working through the book Rails for PHP programmers. To make things interesting I'm using Rails 3 and haml to work through the book, and the book is written using Rails 2.X and erb so some of the examples are outdated.
To the question:
The route example in the book is
map.presentation 'meetings/:meeting_id/presentations/:action/:id',
:controller => "presentations",
:action => "show",
:meeting_id => /\d+/
So that was a pre-Rails 3 route. My adaptation of the above into a Rails 3 route is:
match 'meetings/:meeting_id/presentations/:action/:id', :to => 'presentations#show', :constraints => {:id => /\d/}
My adaptation works for the destroy action, but not for the edit action... and due to my inexperience I don't know what I'm doing wrong. From the article here (http://www.engineyard.com/blog/2010/the-lowdown-on-routes-in-rails-3/) it looks like I'm doing it right, but something isn't right.
The link_to helpers that produce the urls are as follows
= link_to 'edit', :controller => 'presentations',
:action => 'edit',
:meeting_id => presentation.meeting.id,
:id => presentation.id
# Incorrectly Produces: http://localhost:3000/presentations/edit?meeting_id=2&id=1
= link_to 'destroy', { :controller => 'presentations',
:action => 'destroy',
:meeting_id => presentation.meeting.id,
:id => presentation.id },
:confirm => 'Are you sure?',
:method => :delete
# Correctly Produces: http://localhost:3000/meetings/2/presentations/destroy/1
Your help would go a long way to clearing up my routing haziness. Thanks so much!
EDIT
Here's the non-working routes.rb file in its entirety:
UserGroup::Application.routes.draw do
get "presentations/new"
get "presentations/edit"
get "sessions/new"
get "users/index"
get "users/show"
get "users/new"
get "users/edit"
get "meetings/index"
match '/meetings/show/:id', :to => 'meetings#show', :as => 'meeting'
match '/meetings/new', :to => 'meetings#new', :as => 'new_meeting'
match '/meetings/edit/:id', :to => 'meetings#edit', :as => 'edit_meeting'
match 'meetings/:meeting_id/presentations/:action/:id', :to => 'presentations', :constraints => {:id => /\d/}
#default route
match ':controller(/:action(/:id(.:format)))'
end
EDIT 2
Thanks to codykrieger I took a look at the rest of the routes file (I know, duh right?). Apparently, all those get "..." routes are added when using the rails generator and help to make some default connections in the app. I commented out the get "presentations/edit" line and, wonder of wonders, my routing adaptation actually does work.
This works:
UserGroup::Application.routes.draw do
get "presentations/new"
#get "presentations/edit"
get "sessions/new"
get "users/index"
get "users/show"
get "users/new"
get "users/edit"
get "meetings/index"
match '/meetings/show/:id', :to => 'meetings#show', :as => 'meeting'
match '/meetings/new', :to => 'meetings#new', :as => 'new_meeting'
match '/meetings/edit/:id', :to => 'meetings#edit', :as => 'edit_meeting'
match 'meetings/:meeting_id/presentations/:action/:id', :to => 'presentations', :constraints => {:id => /\d/}
#default route
match ':controller(/:action(/:id(.:format)))'
end
I played around with the order of the routes in the file and also found that if I put my route above all the auto-generated routes, without commenting out the get "presentations/edit" line, my route still has the intended effect.
This also works:
UserGroup::Application.routes.draw do
match 'meetings/:meeting_id/presentations/:action/:id', :to => 'presentations', :constraints => {:id => /\d/}
get "presentations/new"
get "presentations/edit"
get "sessions/new"
get "users/index"
get "users/show"
get "users/new"
get "users/edit"
get "meetings/index"
match '/meetings/show/:id', :to => 'meetings#show', :as => 'meeting'
match '/meetings/new', :to => 'meetings#new', :as => 'new_meeting'
match '/meetings/edit/:id', :to => 'meetings#edit', :as => 'edit_meeting'
#default route
match ':controller(/:action(/:id(.:format)))'
end
I'm thinking that the latter is the better way to go and I should make my custom routing declarations above the standard generated ones, but I'm not sure. If someone out there wants to comment on which practice is better, or if it's better to entirely remove the generated ones if I want to specify my own, I'd love to hear it.
Thanks all :)
Routing is done on a first match basis (top to bottom) in the routes.rb file.
So you can keep all routes as you have done above if you want, and Rails will use the first one that matches. However, its messy, potentially buggy and totally unnecessary. So the "match..." lines in your code should be enough, and you can remove the "get..." lines.
Furthermore, your "match...presentations...." line has a bug, it should be
...{:id => /\d+/}
else it will validate only 1-digit length ids.
Finally, as far as your overall routes.rb is concerned, you do not need to do
link_to 'edit', :controller => 'presentations',
:action => 'edit',
:meeting_id => presentation.meeting.id,
:id => presentation.id
Instead, you should use edit_meeting_path, new_meeting_path etc. For instance
<%= link_to "New meeting", new_meeting_path %>
<%= link_to "Edit meeting", edit_meeting_path(#meeting) %>
Finally, you should read Rails Routing from the Outside In for best practices on how to design nested routes etc.