How to get a named route from a class in rails? - ruby-on-rails

I have a common partial for index where i want to insert some links.
On this links i would like to use the named_routes, like
link_to "Say hi",things_path(:param1=>:hello, :params2=>:there)
but i dont know if things_path is users_path, places_path or reviews_path, because this partial is shared for all controllers. There is any way to get the named route associated to the class or the current controller.
I want something like this
link_to "Say hi", path_of(#current_class)(:param1=>:hello, :params2=>:there)

There are several approaches to this. The simplest thing is to rely on polymorphic routing, such as: link_to "Say hi", #my_object. In this case rails will look at the class of #my_object and its current state (new_record?) and use the appropriate route and restful action. Assuming your partial is named _foo.html.erb then this can be as simple as
link_to 'Say hi', foo
... which is pretty awesome. This question has been asked before, here: Polymorphic Routes in Rails - in views but I guess it's hard to find answers without knowing the magic words "polymorphic routing" :-)

A path helper like cars_path is ultimately just a shortcut to setting :controller, :action and other params like :id. If you want to make the controller always equal to the current controller you can just say
link_to "Say hi", :action => "index", :param1=>:hello, :params2=>:there
Because the :controller option is omitted, it will be assumed to be the current controller.

Related

basic routing - how to create a link_to path from match

Ok, say you have this:
match "tutor_appointments/new_appt" => "tutor_appointments#new_appt"
How do I create a link_to path from it?
Would it be something like this: (it doesn't work, btw)
<%= link_to "New Appointments", controller:tutor_appointments, method:new_appt %>
I'm always confused on routing stuff when it comes to figuring out how to do link_to link.
I do understand that tutor_appointments is the controller and new_appt is the method.
Ideally, you would name the route:
http://guides.rubyonrails.org/routing.html#naming-routes
And then you can refer to the route by that name.
eg. if you had:
match "tutor_appointments/new_appt" => "tutor_appointments#new_appt", as: 'new_appointment'
Then you could do:
link_to 'New Appointments', new_appointment_path
However, in this case it sounds like what you actually want is resource routing:
http://guides.rubyonrails.org/routing.html#resources-on-the-web
And you want a 'new' action for your 'tutor_appointments' resource.

Why is link_to with an absolute url considered technically superior to targetting controller action?

New to rails, so if this is discussed somewhere, just link me off: I had a good search but all I could find were people trying to figure out how to use link_to, not any discussion of this comment:
link_to "Profile", profile_path(#profile)
# => Profile
in place of the older more verbose, non-resource-oriented
link_to "Profile", :controller => "profiles", :action => "show", :id => #profile
# => Profile
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to
I get that the latter is more verbose, and thus undesirable, but the former seems like a strange thing to be recommending.
If I have an action at say: /blah/add and I link to it using:
link_to "Link", link_add_path
Then I'm linking to mysite.com/link/add. This is a hard coded url.
If I change the route that this maps to, I have to change every instance of link_to in my code base to point to the new absolute url. This seems crazy.
However, if I link to it using:
link_to "Link", :controller => "thing", :action => "add"
Then the url is dynamically determined. If I have to change the path all I do is edit config/routes.rb and not touch any of my code. This seems like much lower maintenance.
I appreciate it's slightly more complex than that, the blah_path variable is not actually a static route, and actually contains some smarts like the application base url and prevents you from linking to urls that don't exist, but it seems like a step backwards to facilitate a fractionally less verbose syntax.
So, what's up with that?
What technical reason would you choose the former link_to syntax over the latter?
"You're doing it wrong" :P
Seriously though: use named resources, and here's why that's cool:
Example:
you've got this in your routes file:
resources :user_orders
And you are using "user_orders_path" everywhere. Then you do a refactor and decide (because the orders are now generic) that you want the controller to be called "orders" but you don't want to break all your old code. you can do this:
resources :user_orders, controller: "orders"
And your existing links will continue to work! (plus you can add a "orders" resource to move things over to the new scheme)
There's also neat things like named links:
match 'exit' => 'sessions#destroy', :as => :logout
I'd also like to add, if you needed to refactor your controller using the old link syntax - you'd still have to change a pile of controller links!
Then I'm linking to mysite.com/link/add. This is a hard coded url.
No, it's not. link_add_path is a method generated by Rails that points to a specific route in your config/routes.rb. You can see this by running
rake routes | grep link_add
If I change the route that this maps to, I have to change every instance of link_to in my code base to point to the new absolute url. This seems crazy.
No, you don't. Take the following example
get "link/add", as: :link_add, controller: :links, action: :add
If I run the above
rake routes | grep link_add
I get
link_add GET /link/add(.:format) links#add
But what if I change the name of my controller to UrisController? Just change the route in config/routes.rb
get "link/add", as: :link_add, controller: :uris, action: :add
and now you have
link_add GET /link/add(.:format) uris#add
The link_to's don't have to change because the link_add_path method is still mapped to the newly modified line in my config/routes.rb because the route name is the same. With your more explicit way of specifying controllers/actions for every link_to, you have to go through every link and update it manually to reflect the new controller: :uris controller.
Read about Naming Routes in the rails guide.

Generate a `link_to` to the controller action `edit`, dynamically

I am using Ruby on Rails 3.0.7 and I would like to generate a link_to to the controller action edit, dynamically. I have to use it in a partial template but the issue is that I am rendering that same partial template for different model data (that is, I pass local variables of different class instances in that).
So I can not use the route "magical RoR way"
`edit_<singular_name_of_the_resource>_path(<resource_class_instance>)`.
I would like to make something like the following:
link_to( #resource_class_instance, :action => 'edit') # This example is wrong, but it suggests the idea
Is it possible? If so, how can I do that?
You can write routes using the "array style" like this :
= link_to "Edit", [:edit, #your_resource]
There is a edit_polymorphic_url and (edit_polymorphic_path) helper available:
https://github.com/rails/.../polymorphic_routes.rb#L32

Adding a route to match a specific pattern

I have a controller in Ruby on Rails and I would like to do the following:
When a user is trying to access the controller I want to match some parameters. For example
domain.com/hello/19213/sayHello
I want to translate this to:
domain.com/hello/:id/:method
in my routes files.
Keep in mind that :method parameter might not exist but :id will always be there.
In addition if it is possible I would like to match the specific :method with a method in my controller. If not I plan to use a switch case.
Can someone provide an example for this and what I have to put in my routes.rb?
I found this:
match ':controller(/:action(/:id(.:format)))'
But I believe that this is somehow different as I only want to match router for the specific controller not every controller in my project.
Thanks
By method, I assume you mean a method you have in your model. If that is the case, I believe you want something like this in your routes.rb
match ':controller/:id(/:method)'
The parentheses around :method mean that it is optional.
If you do not include a method, it will evaluate your SHOW action with params[:id] = :id
If you do include a method, it will evaluate the :method with params[:id] = :id
This is for methods you have defined in your controller

renaming routes (map, link_to, to_param) in rails

I'm having a little issue...I setup a rails application that is to serve a german website. To make use of Rails' internal pluralization features, I kept all my models in english (e.g. the model "JobDescription").
Now, if I call "http://mysite.com/job_descriptions/", I get all my job_descriptions....so far, so good. Because I didn't want the english term "job_descriptions" in my url, I put the following into my routes.rb
map.german_term '/german_term', :controller => 'job_descriptions', :action => 'index'
map.german_term '/german_term/:id', :controller => 'job_descriptions', :action => 'show'
If I call "http://mysite.com/german_term/" or "http://mysite.com/german_term/283" I get all my job_descriptions, which is fine.
However, to make the URL more SEO friendly, I'd like to exchange the id for a more userfriendly slug in the URL. Thus, I put the following in my job_description.rb:
def to_param
"#{id}-#{name.gsub(/[^a-z0-9]+/i, '-')}"
end
which, whenever I use "job_description_path" in any link_to method, renders my URLs out to something like "http://mysite/job_descriptions/13-my-job-description-title".
However, and this is where I'm stuck, I'd like to get "http://mysite/german_term/13-my-job-description-title". I already tried to exchange the "job_description_path" with "german_term_path" in the link_to code, but that only generates "http://mysite/german_term/13". Obviously, to_param isn't called.
One workaround I found is to build the link with:
<%= link_to job_description.name, german_term_path(job_description.to_param) %>
But that's rather tedious to change all the link_to calls in my code. What I want is to replace "job_description" by "german_term" whenever it occurs in a URL.
Any thoughts?!?
Regards,
Sebastian
I think you're going to need to use the restful route helpers to get what you want.
In that case, it wouldn't take much re-factoring (assuming you've mapped JobDescriptions as a resource). Leave your to_param as is and change your JobDescriptions route to something like the following:
map.resources :job_descriptions, :as => 'german_term'
Hope this helps!
Rails only utilizes the
def to_params
end
URL builder when you are using a restful route/link helper. The only way I am aware of is to do it similar to how you did, unless you are willing to just scrap your english language links and do it all in German. In that case, just get rid of the named route lines and change the to_params to use the correct name field from the database. At that point, the REST routes should behave correctly.

Resources