Two same routes doing different actions error - ruby-on-rails

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.

Related

How can I redirect to a specific controller/action with similar routes?

My routes are redirecting to the same controller even when I specified different properties inside my routes.rb file.
These are my routes.
match ':clube_id' => 'clubes#show', :as => 'clean_cluble', via: [:get]
match ':project_id' => 'projects#show', :as => 'clean_project',via: [:get]
These are the links that I am using.
=link_to 'Project', :controller => "projects", :action => "show", :project_id=>'xxxxx'
=link_to 'Clube', :controller => "clubes", :action => "show", :id=>'cccc'
The link for projects works well, but the linl for clubes is redirecting to projects controller. that is the problem.
The URLs that I spect are:
http://host_name/project_name
http://host_name/clube_name
You didn't specify different properties, both routes look's identical for Rails. The match method expect any string(or id) in the ':clube_id' or ':project_id', for example:
host_name/soho_project or host_name/1
How is Rails can recognize for a which model it's related? It can be a Project or Club. I suggest add something like the anchor to a match method.
match 'club/:clube_id' => 'clubes#show', :as => 'clean_cluble', via: [:get]
match 'project/:project_id' => 'projects#show', :as => 'clean_project',via: [:get]
and helpers:
= link_to 'Project', clean_project_path(:project_id=>'xxxxx')
= link_to 'Clube', clean_cluble_path(:clube_id=>'cccc')
Read more about routes from the Rails guides.

How do I stop routes for user profile conflicting with other routes in ruby on rails?

How would I stop these 2 routes from clashing:
match "users/:id/edit", :to => "users#edit", :via => :get, :as => :settings
match '/:username', :controller => 'users', :action => 'show'
When I visit localhost:3000/settings it tries to find a user in my users table with the username "settings".
What I plan on doing is having a page settings then have things like settings/privacy, settings/general and also edit_profile
How can I have this but also still get to user localhost:3000/username
It must be possible as I've seen many ROR sites doing this.
Kind Regards
The settings route you have here is pointing to the users edit path.
Using settings_path will direct to users/:id/edit
What you want is:
match "/settings", :to => "users#settings"
match "/settings/:category", :to => "users#settings"
match '/:username', :controller => 'users', :action => 'show'
Now '/settings' will direct you to the settings method. The second additional route will handle the specific setting to route to (ie /settings/privacy) which will allow you to evaluate what to do in the view based on the params[:category] parameter available in your settings action. Alternatively this will give a privacy settings path:
match "/settings", :to => "users#settings"
match "/settings/privacy", :to => "users#settings", :as => :privacy_settings
match '/:username', :controller => 'users', :action => 'show'
No need for the :as statement, settings_path will still work. Then in the settings method of your UsersController you can use session information(current_user) to render the proper user.
The RESTful edit path will be handled and available through this statement in your routes file:
resources :users
So 'users/:id/edit' will still work.

How to name a route in rails

I have some routes looking like this :
match 'hotels/:action(/:id)', :controller => 'hotel', :action => /[a-z]+/i, :id => /[0-9]+/i
And i want to use something like hotels_dislike_path somewhere in my code which refers to /hotels/dislike
How can i do that?
From the routing guide:
3.6 Naming Routes
You can specify a name for any route using the :as option.
match 'exit' => 'sessions#destroy', :as => :logout
So, in your case, that would be:
match 'hotels/:action(/:id)', :controller => 'hotel', :action => /[a-z]+/i, :id => /[0-9]+/i
match 'hotels/dislike(/:id)', :controller => 'hotel', :id => /[0-9]+/i, :as => :hotels_dislike
match 'hotels/like(/:id)', :controller => 'hotel', :id => /[0-9]+/i, :as => :hotels_like
I don't think there's a way to do this dynamically (so you have to define one route for each action, basically). However, you can just define a couple of routes (like above) for the most used actions, and just use hotels_path :action => :really_like for more uncommon actions.
A lot has changed in the world of Rails since 2011 - this is how you would accomplish the same goal in Rails 4.
resources :hotels do
member do
post 'dislike'
post 'like'
end
end
The resulting routes:
dislike_hotel POST /hotels/:id/dislike(.:format) hotels#dislike
like_hotel POST /hotels/:id/like(.:format) hotels#like
hotels GET /hotels(.:format) hotels#index
POST /hotels(.:format) hotels#create
new_hotel GET /hotels/new(.:format) hotels#new
edit_hotel GET /hotels/:id/edit(.:format) hotels#edit
hotel GET /hotels/:id(.:format) hotels#show
PATCH /hotels/:id(.:format) hotels#update
PUT /hotels/:id(.:format) hotels#update
DELETE /hotels/:id(.:format) hotels#destro
Notice thats rails prefixes instead of postfixes the action - dislike_hotel_path not hotels_dislike.

Why to add a connection in routes file when using link_to in rails 2

I was trying to accomplish the following:
<%= link_to "Log out", { :controller
=> 'users', :action => 'logout' }, :class => 'menulink2' %>
But it didn't work, it always redirected me to a show view. I had to had the following to my routes.rb:
map.connect 'users/logout',
:controller => 'users', :action =>
'logout'
Why didn't rails recognize the action I was passing ('logout') ?
That logic has to be specified somewhere. There's got to be some mapping from the hash {:controller => 'users', :action => 'logout'} to a url, and the place that's done in rails is the routes.rb file. In older versions of rails many routes.rb came with a default at the end:
map.connect ':controller(/:action/(:id(.:format)))'
Which would make it so that most any :controller, :action hash could be specified and then routed to host.url/:controller/:action.
With the more modern versions resource-based routes are heavily favored, and controllers which don't follow rails' REST conventions (i.e. having only :index,:show,:create,:new,:edit,:update,:destroy methods) generally have to have their routes explicitly specified in some way.
(Either with map.resources :users, :collection => {:get => :logout} or with map.connect( 'some_url', :controller => 'users', :action => 'logout'}))
I'm guessing, but the reason they did that is probably that the actions of a controller are really just its public methods.
It's frequently nice to have public methods in your controllers that aren't url-end-points for testing purposes.
For instance, you could have before_filters as public methods that you might want to test without having to use #controller.send(:your_before_filter_method) in your test code.
So they whitelist the resource actions, and make the others unreachable by default. Let me look through the rails changelog and see if I'm right.

creating a link_to for custom route

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)

Resources