creating a link_to for custom route - ruby-on-rails

I have a custom route (if I am doing that correctly, this is the first time I have done this) that looks like this:
map.connect 'purchases/type/:type', :controller => 'purchases', :action => 'index'
so I want to create a link_to that would use that url /purchases/type/(somenumber)
or I am completely open for a better way to do it.
Edit:
I am trying to use a category (type) to filter on the index. So if I click the link that would be /purchases/type/1 that would show all the items from type 1. I dont want this in the show, and I could do it with /purchases/?type=1, but im trying to make the urls look better.

Untested but I believe this is what you want...
map.purchase_type 'purchases/type/:type', :controller => 'purchases', :action => 'index'
Then
link_to 'foo', purchase_type_path(:type => 'your_type')
Good luck.

Based on http://www.tutorialspoint.com/ruby-on-rails-2.1/rails-routes.htm (section "named routes"), I'd try the following:
map.purchases_for_type 'purchases/type/:type', :controller => 'purchases', :action => 'index'
And I assume you'd then call it with link_to 'link text', purchases_for_type(#type_param)
For reference, I'll include the Rails3 way to do it:
match '/purchases/type/:type' => 'purchases#index', :as => "purchases_for_type", :via => "get"
Or better yet (RESTful):
match '/type/:type/purchases' => 'purchases#index', :as => "purchases_for_type", :via => "get"
You'd then call it with link_to 'link text', purchases_for_type(#type_param)

Related

Two same routes doing different actions error

I've the same two routes (see below) which can be activated by two different buttons, which call two different buttons.
My scenario is:
I've two buttons on the same page ("Release Version" and "Publish Version"). For each of these buttons I call a different remote method (exec_client and exec_release).
So, for questions of routes ambiguity (I think...) I couldn't call the second function I've defined on my routes.rb. Every time when I click on "Publish Version" button I call the exec_client method, whereas this button was supposed to call the exec_release method.
My question is: What can I do to fix it?
Below my routes code, where I think is the problem of code.
match 'projects/:id/repository', :action => 'exec_client', :controller => 'repositories', :via => :post
match 'projects/:id/repository/:branch', :action => 'exec_client', :controller => 'repositories', :via => :post
match 'projects/:id/repository', :action => 'exec_release', :controller => 'repositories', :via => :post
match 'projects/:id/repository/:branch', :action => 'exec_release', :controller => 'repositories', :via => :post
If you need another piece of my code, please ask and I'll put here.
Rails routes have a priority based on a position in routes.rb file. Simple explanation of what is happening: some of your routes are more 'common' than others. So, for example:
match 'projects/:id/repository', :action => 'exec_client', :controller => 'repositories', :via => :post
match 'projects/:id/repository/:branch', :action => 'exec_client', :controller => 'repositories', :via => :post
Second route has no way to be triggered, because requests to /projects/:id/repository will be routed to exec_client action even if they have :branch parameter (actually, any number of parameters). So, you need to follow this simple convention: more specific routes at the beginning of the file, more common routes at the end of the file.
Also, it's a bad practice to use identical routes (identical uri and HTTP verbs). According to route priorities, you will always trigger the highest variant (the one, who was defined earlier). The simplest thing you can do, is to make a separate route for each of your actions.
So, here's an example what should get you going:
match 'projects/:id/repository/publish', :action => 'exec_client', :controller => 'repositories', :via => :get
match 'projects/:id/repository/release', :action => 'exec_release', :controller => 'repositories', :via => :get
This will create a two separate routes for your actions. From what I've seen - :branch parameter is optional. You can check for it's presence in the controller code. Also, I suggest you to read Rails Guide: Routing. This way, you learn about REST and Rails routing basics.

Custom Routing in Rails

I've looked around for a while now, but I'm not sure how best to describe my request to google, so thought I'd ask here ;)
In rails, I know that when you nest restful routes, you generally get something like:
http://localhost/categories/1/articles/2
If you want something more meaningful, you can use slugs or friendly_id to get something like
http://localhost/categories/all-your-needs/articles/rock-out-with-this-article
(assuming you have unique names).
My question is, how can I remove the controller from the url rewriter so you get something like:
http://localhost/all-your-needs/rock-out-with-this-article
Is this possible?
Yes it is. You can use something like this:
Rails 2:
map.show_article ':category/:article', :controller => "articles", :action => "show"
Edit:
Ok. Here you have the urls for the other REST actions:
map.edit_article ':category/:article/edit', :controller => "articles", :action => "edit".
For update add :conditions => { :method => :post } to the previous one.
For delete, use the first one with :conditions => { :method => :delete }.
For new and create, you can use:
map.new_article ':category/new', :controller => "articles", :action => "new"
and for create the same but with :conditions => { :method => :post }. I hope I've been able to help you!

Reverse rails routing: find the action name from the URL

I understand how to turn :controller, :action, :etc into a URL. I'm looking to do the reverse, how can the action that the rails router will call be found from the URL?
With Rails 3 you can do:
Rails.application.routes.recognize_path('/areas/1')
=> {:controller=>"areas", :action=>"show", :id=>"1"}
someone else might have a shorter way to do this, but if you are just evaluating a URL, then you go to the ActionController::Routing::RouteSet class
for a config.routes.rb
map.resources :sessions
the code to find is:
ActionController::Routing::Routes.recognize_path('/sessions/new', {:method => :get})
#=> {:controller => 'sessions', :action => 'new'}
Right:
ActionController::Routing::Routes.recognize_path('/sessions/1/edit', {:method => :get})
#=> {:controller => 'sessions', :action => 'edit', :id => 1}
Wrong - without the method being explicitly added, it will default match to /:controller/:action/:id:
ActionController::Routing::Routes.recognize_path('/sessions/1/edit')
#=> {:controller => 'sessions', :action => '1', :id => 'edit'}
If you are within the action and would like to know, it is quite a bit easier by calling params[:action]
everything you ever wanted to know about routeset can be found here: http://caboo.se/doc//classes/ActionController/Routing/RouteSet.html#M004878
Hope this helps!

Creating a Custom Rails Route

I am attempting to create a custom route in rails and am not sure if I am going about it in the right way. Firstly I have a RESTful resource for stashes that redirects to mystash as the controller:
map.resources :stashes, :as => 'mystash'
site.com/mystash goes to :controller => 'stashes', :action => 'show'
Which is what I want. Now is where it gets somewhat confusing. I would like to be able to add conditional params to this route. Ultimately I would like to have a route that looks like this:
site.com/mystash/zoomout/new/quiz_on/
I have places this in routes:
map.connect 'mystash/:zoom/:nav_option/:quiz',
:controller => 'stashes',
:action => 'show'
map.connect 'mystash/:zoom/:nav_option',
:controller => 'stashes',
:action => 'show'
map.connect 'mystash/:zoom',
:controller => 'stashes',
:action => 'show'
map.connect 'mystash',
:controller => 'stashes',
:action => 'show'
My routes have ended up looking like this in the browser:
site.com//mystash/zoomin?nav_option=New&quiz=quizon
and this is what one of my links looks like:
<%= link_to "In", stash_path("zoomin", :nav_option => #nav_option, :quiz => #quiz) %>
Any help is appreciated, I am pretty new to custom routes!
You should be giving these routes different names instead of the default, or you should be specifying your route with a hash and not a X_path call. For instance:
map.stash_zoom_nav_quiz 'mystash/:zoom/:nav_option/:quiz',
:controller => 'stashes',
:action => 'show'
map.stash_zoom_nav 'mystash/:zoom/:nav_option',
:controller => 'stashes',
:action => 'show'
Keep in mind that when you declare a named route, the parameters in the path must be specified in the X_path call with no omissions, and not as a hash.
link_to('Foo', stash_zoom_nav_quiz_path(#zoom, #nav_option, #quiz))
link_to('Bar', stash_zoom_nav_path(#zoom, #nav_option))
The alternative is to not bother with named routes and let the routing engine figure it out on its own:
link_to('Foo', :controller => 'stashes', :action => 'show', :zoom => #zoom, :nav_option => #nav_option, :quiz => #quiz)
If you're uncertain what routes are defined, or how to call them, always inspect the output of "rake routes" very carefully. You can also write functional tests for routes with the assert_routing method.

routes.rb explicitly choose template

I would like to create one .erb file to be the output for a number of tiny actions that are just returning JSON. So with routes similar to:
map.json 'contacts_json', :controller => 'contacts', :action => 'get_json'
map.json 'cal_json', :controller => 'calendar', :action => 'get_json'
...
but this requires I create a contacts erb, and a calendar erb so on and so forth. Is there a way to explicitly tell them to use a json erb? Something like:
map.json 'contacts_json', :controller => 'contacts', :action => 'get_json', :view => 'layouts/json.html.erb'
I'm not sure it answers your question but using render :text => #foobar.to_json does wonders in some cases.
No -- you specify what view template to render in the controller action.

Resources