Rails: restful resource routing with action_controller_path - ruby-on-rails

I am putting a randomize def in my controller and would like to access it with a restful route. The route should be accessed with the following:
<%= link_to "Randomize", random_reader_path %>
But I cannot figure out how to get this route to appear in rake routes or configure it correctly in my routes.rb file.
The random method will do the same thing as index only provide a random page content #variable
Currently I have my reader Controller as
resources :reader
in my routes.rb

Add more RESTful actions!
resources :reader do
get 'random', on: :collection
end
The route will be random_readers_path, though.

Related

How to change default path/url in routes in Rails 4

I'm working on a simple reservation application. Here are my routes
resources :users do
get 'reservations', on: :member
end
resources :listings do
resources :reservations
end
When I try to make a reservation, action reservations#new takes me to reservations_path . Of course I'm getting error as this path doesn't exist. I'd like action new to take me to listing_reservations_path instead. I was hopping it will be done automatically since resources :reservations is in nested resources. I read about routes and tried many things but can't find any working way of doing it. Is it possible?
You seem to be unclear on the nature of routes. The action reservations#new exists independently from any route. A route is just a way to map a URL path to a controller and action. If you are trying to do something like:
redirect_to controller: :resources, action: :new
You will have trouble, as all of your routes require some context. Instead, you need to provide whatever the URL helper you're using with a context:
redirect_to listing_reservations_path(#listing)
link_to "New Reservation", new_listing_reservation_path(#listing)
link_to "Reservation", [#listing, #reservation]

Rails redirection to show when redirected to other action in same class

My Task is to submit a form to place_order action inside Checkout controller.
This is how I wrote form in my view file i.e
<%= form_for (#order), url: {action: "place_order"} do |f| %>
It does reach inside this method and as I save object i want to redirect to some other method in the same class. This method name is thank_you. My code looks like this inside place_order method
if #order.save
redirect_to :action => 'thank_you'
else
...
end
But it redirects to show method of this class. If I change redirect to other class, it redirects fine but on other action of same controller, it always redirects to show.
Here is how I defined my routes
resources :checkout
resources :photos
devise_for :users
resources :carts
post 'checkout/place_order'
match 'checkout/thank_you', to: 'checkout#thank_you', via: [:get]
I need some expert opinion on this. Please help.
Move your thank_you route above resources :checkout.
From Rails guides:
Rails routes are matched in the order they are specified, so if you
have a resources :photos above a get 'photos/poll' the show action's
route for the resources line will be matched before the get line. To
fix this, move the get line above the resources line so that it is
matched first.

"Create" route path helper

I find the resource route method quite convenient, but I totally hate that it does not create create and destroy path helpers.
I understand that writing
<% form_for(#object) %>
is supposed to automatically get the route name, and that we can play with arrays or symbols to automatically get the namespace/prefixes when they exist, but I have many routes with complicated scope definitions, and not being able to get create_xxx helpers totally annoys me
Is there no simpler solution than to write ? (I am trying to keep the default RESTful URLs while generating the helpers)
complicated_scope do
resources :my_resources, except: [:create, :destroy] do
post '', on: :collection, action: :create, as: 'create' # plus this generates a pluralized version, not very intuitive `create_complicated_scope_my_resourceS_path`
delete '', on: :member, action: :destroy, as: 'destroy'
end
end
EDIT. My example of 'somewhat complicated scope'
# Company access routes under /company/
namespace :company do
# I need a company id for all nested controllers (this is NOT a resource strictly speaking, and using resources :companies, only: [] with 'on: :collection' doesn't generate appropriate urls)
scope ':company_id' do
# Company administrators
namespace :admin do
# There is a lot of stuff they can do, not just administration
namespace :administration do
# There are several parameters grouped in different controllers
resources :some_administrations do
... # finally RESTful actions and others here
end
end
end
end
end
Resourceful routing does create create and destroy helpers, but they're implied by the type of HTTP request being made (POST and DELETE respectively) so the routing helper methods should work fine with the code you've provided.
Suppose you have the following route definition:
complicated_scope do
resources :my_resources
end
end
As a simple example, in the case of delete, you could use a named route like so:
link_to "Delete [resource]", complicated_scope_resource_path(id: #my_resource.id), method: :delete
Since the HTTP verb disambiguates the controller action this helper method routes to the destroy method of the controller.
Alternatively, you should be able to use the array syntax as well.
link_to "Delete [resource]", [:complicated_scope, #my_resource], method: :delete
The same goes for forms:
<%= form_for [:complicated_scope, #my_resource] do |f| %>
If #my_resource is a new object (not persisted), as in the case of a new action this would be equivalent to sending a post request to /complicated_scope/my_resource with the form params going in the body of the request.
Alternatively if #my_resource exists, as in the case of an edit action, the above would be equivalent to sending a PUT/PATCH which will route to the update action of your controller with /complicated_scope/my_resource/:id/update.

How to add parameter to rails index action/method?

I want to pass a parameter to the index action, but the I'm only getting the show action.
routes.rb:
Test1::Application.routes.draw do
resources :blog
end
blog_controller.rb:
def show
# code
end
def index
# code
end
View url that send to show action instead to index action:
My link
What should I add in routes file or in view?
Output of my routes:
$ rake routes
blog GET /blog(.:format) {:action=>"index", :controller=>"blog"}
blog GET /blog/:id(.:format) {:action=>"show", :controller=>"blog"}
The command line will show you routes you can use with rake routes
The route you want is blogs_path and you can add a parameter on to that, e.g. blogs_path(other_item => :value).
Exactly how will depend on whether you are try to use it in a controller, another view, etc.
For the view have: <%= link_to 'My Link', blogs_path(:other_item => value) %>
It sounds like you want 2 routes:
/blogs/:other_param
/blogs/:id
But, for as smart as Rails is, it can't figure out whether the param is meant to be treated as an other_param or as an id.
So the simplest solution is to add this route to the resources defaults like so:
resources :blogs
get "/blogs/other_param/:other_param", to: "blogs#index", as: "other_param_blogs"
That way Rails knows that if you're going to /blogs/other_param/current, then it will treat current as the :other_param.
Use below code to pass parameter:
My link
or
<%= link_to "My link", blog_path(name: "test") %>
above code will redirect to index action with name as key and test as parameter,

My routes has resources :home, but rspec is saying routes not defined?

My homecontroller has:
def about()
end
And I have a rspec test that does GET 'about' and it fails saying that there is no route that matches.
doesn't this map all actions in the controller:
resources :home
or do I have to explicitly state each action in the home controller?
resources :home sets up the default RESTful routes - index, show, new, create, edit, update, and destroy. Any additional routes have to be specified. It looks like you're adding a simple collection route, so you'd specify it like this:
resources :home
collection do
get 'about'
end
end
This will give your the route '/home/about'. I assume this is Rails 3. If you're in Rails 2.x, do it like so:
map.resources :home, :collection => {:about => :get}
And from the command line, you can always see what routes you have available with this command:
rake routes
I hope this helps!
EDIT: If you want a default route, you can add this:
match ':controller(/:action(/:id))'
This is a default route that will match any generic requests.
FULL ARTICLE: Routing in Rails 3 is its own beast. There have been a lot of questions about it lately, so I've created a very detailed article with code samples to help others:
Routing in Ruby on Rails 3
I created a companion Rails 3 app that can be downloaded to play around with, as well:
https://github.com/kconrails/rails3_routing
If you have any questions, please hit up my site and ask. Thanks!
resources will give you the 7 CRUD methods for a controller, if you want additional actions, you need to do something like the following:
resources :homes do
collection do
match "about" => "homes#about", :as => "about"
end
end
Then you'll also have an additional about_homes_path/url helper available.

Resources