Rails: a singular resource nested on the index of another resource - ruby-on-rails

I have an User(plural) and a Subscription(singular) controllers. I am wondering if I can set a route like the following:
/users/subscription/edit
which means editing the subscription of the current user. All examples I see are like /users/1/subscription/edit
This way any user can point to this same url and it will direct to their settings page.

Make the routes like :
match '/users/subscription/edit' => 'subscription#edit' : as => "subscription_edit"
OR
match '/users/subscription/edit', :controller => 'subscription', :action => 'edit' : as => "subscription_edit"

Related

Ruby on Rails - Setting a Custom Route with Custom Action

i'm a RoR beginner using rails 3.2.3.
I have a products resource and a nested Availability resource under it.
My routes are:
/products/:product_id/availabilities
which is working great.
However, my availability model allows to set the price of the product on an exact date, for e.g.: today the product 'x' will have 'y' availability (it is an integer) and 'z' price (price is also an attribute of the Availability Model).
My question is, I now want to add a page that allows the modification of prices (without creating a new Price Model), similar to the one I have for availability. I'm only using the index action, as it will show all the availabilities for that only selected product.
How can I create a route like:
/products/:product_id/availabilities/prices
I tried adding this to my routes rb:
match '/products/:id/availabilities/prices', :action => 'indexP', :via => [:get], :controller => 'prices'
match '/products/:id/availabilities/prices', :action => 'createP', :via => [:post], :controller => 'prices'
It is worth noting that I am using a prices controller to interact with the same availability model, but that shouldn't be a problem.
I also created in that prices controller the indexP and createP actions.
In my Availabilities View I created an indexP.html.erb to differentiate from the regular index.html.erb which contains the availabilities.
And when I run rake routes I get:
$ rake routes | grep prices
GET /products/:id/availabilities/prices(.:format)
POST /products/:id/availabilities/prices(.:format)
Which is great. However, when I access that URL, I get:
NoMethodError in Availabilities#show
{"product_id"=>"46",
"id"=>"prices"}
Why is it doing the show action instead of my custom match?
Note: I am not after something like: /products/:id/availabilities/:id/prices
just :/products/:id/availabilities/prices
I know this is probably a dumb question but I would appreciate any tips to help me understand what is going on.
Thanks in advance,
regards
How is your product model setup?
If it something like:
resources :products do
resources :availabilities
end
the first match the route does goes to the show action of the availabilities controller.
You have two options here. Limit the availabilities controller scope, with:
resources :products do
resources :availabilities, :only => [:index]
end
or to place your custom match before this block
match '/products/:id/availabilities/prices', :action => 'indexP', :via => [:get], :controller => 'prices'
match '/products/:id/availabilities/prices', :action => 'createP', :via => [:post], :controller => 'prices'
Note that this routes are not restfull. This may get you in trouble later :)
Hope this helps.

Matching routes from an array - Rails Routing

I`m looking to implement links that fit a certain format (seo purposes).
Here`s an example:
match '/activities-Palmdale-California', :to => 'explores#activity_by_city', :location=>'Palmdale-California'
Where the location changes for each city+state.
Is there I way to dynamically loop through an array of cities & states (predefined) in the routes file, without creating additional models etc. ?
You can have parameters in your routes, so something like the following should work:
match "/activities-:location", :to => 'explores#activity_by_city'
and the location should be sent to your controller action in params[:location]. If you want to limit the urls your application will accept to just the locations in a predefined array (we'll call it ValidLocations), you can do it either in the route with the :constraints option:
match "/activities-:location", :to => 'explores#activity_by_city', :constraints => proc { |req| ValidLocations.include?(req.params[:location]) }
or in the controller:
def activity_by_city
...
unless ValidLocations.include?(params[:location])
flash[:error] = "Invalid location."
redirect_to ...
return
end
...
end

Rails routes constraints based on model

Using Rails 3.1. I have the following in my route:
In my model Shop, I have a column called shop_type that has either boutique or saloon. Instead of having the url:
http://localhost/spots/1
I would like to separate it by the shop_type to:
http://localhost/boutique/1
http://localhost/saloon/2
So I added the following to my route:
resources :boutique, :controller => 'shops', :constraints => { :shop_type => 'boutique' }
resources :saloon, :controller => 'shops', :constraints => { :shop_type => 'saloon' }
The problem with this is I can access record ID 1 with shop_type = boutique with either of the URL. Ideally, it should return error when a user tries to access
http://localhost/saloon/1
But the above URL just works fine, which is not what I want.
Also, is there anyway to redirect all shops/1 to the new URL which is by shop_type?
Many thanks.
If you want to do this, then your application is probably telling you that it really wants two separate classes, Boutique and Saloon. Can you do that? If not, why not?
Maybe its better to tell Rails directo allow urls as:
get "/:shop_type/:id", :to => 'shop_controller#show'
And in controller check if the record exist, and return :status => 404 if not:
#shop = Shop.where(:id => params[:id], :shop_type => params[:shop_type]).first
render :status => 404 and return if #shop.nil?
Note that route provided is too greedy and put it after all other routes so it will not 'eat' other request.

Github like routes in Rails

Using github like chain routes in rails
I have URLs similar to this:
'localhost:3000/document_managers/[:module_name]'
'localhost:3000/document_managers/[:module_name]/1/2/3/.' # can be any level deep
Here is the route definition for them:
map.connect '/document_managers/:module',
:controller => "document_managers",
:action => :new_tree,
:module => ["A","B","C"]
map.connect '/docuemnt_managers/:module/*path',
:controller => "document_managers",
:action => "new_tree",
:module => ["A","B","C"]
Here is the problem:
The idea that module name value can't be anything except from the
given above array i.e("A","B","C") like at any time the URL must be something like
localhost:3000/document_managers/A/1 or
localhost:3000/document_managers/B/221/1 or
localhost:3000/document_managers/C/121/1
but that not the case even though
localhost:3000/document_managers/D/121/1 is treated as valid url
and module is set to D even though the "D" is not in listed array
above
I want the the URL localhost:3000/document_managers/A to
also redirect to same action i.e new_tree if the extra parameter isn't
provided as in the URL contain extra parameters
localhost:3000/document_managers/C/121/1 then the URL is redirected
appropriately to the desired controller and action but if the URL only
contain the path until the module name the Rails return a routes
ActionController::UnknownAction I don't know why as I have already
defined the controller and action.
In Rails 3.1, you can do this in your routes file to get what you want:
match '/document_managers/:module',
:controller => "document_managers",
:action => :new_tree,
:constraints => {:module => /[ABC]/}

problem in routes

i want to change the default route in RoR to what i want:
consider the following example...
:controller/:action/:id
which will give you the route in the browser as:
http://localhost:3000/controller/action/id
now i want to change it to...
http://localhost:3000/this-is-what-i-want/id
we can get an alias for the controller and the action as well like...
resources :controller, :as => "my-custom-name"
and if you want to have the alias for the action, then
resources :controller, :path_names => { :action => 'my-custome-name-1', :action => 'my-custome-name-2' }
BUT i want to change the controller and the action at once... if u noticed the above http://localhost:3000/this-is-what-i-want/id path in the question...
need help...
thanks in advance...
You need a named route.
In Rails2:
map.a_name 'this-is-what-i-want/:id', :controller => 'controller_name', :action => 'action_name'
In Rails3:
match 'this-is-what-i-want/:id' => 'controller_name#action_name'
You want to be using Rest routes, rather than controller/action
I'm going to use "balls" instead of "this-is-what-i-want"
resources :balls
Then, when you link to a ball, do link_to(ball.name, ball).
This will give you a link of http://localhost:3000/balls/45
This rails rest cheatsheet is a good start.

Resources