I have a nested resource:
resources :res1 do
resources :res2
end
And I have a custom action in res2:
def my_action
end
which doesn't appear in the list of the pre-generated paths (there is no res1_res2_my_action_url url). I want to refer to my_action using controller and action notation but the following doesn't work:
url_for(controller: [:res1, :res2], action: :my_action)
Why is that?
The resources directive in your routes file will only create default routes for your controller.
#index
#new
#create
#show
#edit
#update
#destroy
If you want to add custom routes, you'll have to declare them like so:
resources :res1 do
resources :res2 do
get :my_action
end
end
you can hard code a specific route that points to action and controller:
get '/pathname', to: 'controller_name#my_action'
Try running rake routes and see what o/p you get,a try to apply in your view
get 'my_action' => "res2#my_action"
and then write
:url => my_action_path
Related
I am a beginner working with Rails: I have this routes.rb:
Rails.application.routes.draw do
resources :requirements
root "department#index"
get "department/about"
end
How can I create a view that has a path like requirements/major?
Thank you so much!
You can extend resources and add custom actions, like this:
resources :requirements do
collection do
get :major
end
end
You'll need an action in the RequirementsController that matches, e.g.
class RequirementsController < ApplicationController
def major
# set up whatever resource 'major' corresponds to
end
...
end
That's at least one way of doing it. You could also have a controller that directly supports the nested 'major' resource, which would be similar to above - just with a controller: 'name of controller' directive inline..
It'd probably pay to get your head around the "Rails Routing from the Outside In" guide: https://guides.rubyonrails.org/routing.html
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.
I have a controller Sagepay, which have number of custom method (not RESTfull resources). How can I write routes for those actions? So far I tried:
namespace :sagepay, controller: :sagepay, as: :sagepay do
post :notification
get :iframe_breaker
get :accept_payment
end
This however tries mapping to sagepay/sagepay_controller instead simple sagepay_controller.
Obviously I can do this:
match '/sagepay/notification' => 'sagepay#notification', via: :post, as: sagepay_notification
(etc)
which works, but this is not a solution I am looking for. Is there any way I can write it in common block?
The reason you get sagepay/sagepay_controller is the reason why namespaces are used. In order to get sagepay/notification you can define a resource and add collection routes within it, as follows:
# config/routes.rb
resource :sagepay, controller: :sagepay do
collection do
post :notification
get :iframe_breaker
get :accept_payment
end
end
Update:
In order to define only the routes defined within the collection and avoid definition of the seven restful routes that Rails create you can pass in only option to the resource definition as follows:
# config/routes.rb
resource :sagepay, controller: :sagepay, only: [] do
collection do
post :notification
get :iframe_breaker
get :accept_payment
end
end
I think I found the solution:
scope 'sagepay', controller: :sagepay, as: :sagepay do
post :notification
get :iframe_breaker
get :accept_payment
end
I am trying to make a controller with one action and when i try and go to the localhost:3000/controllername/action i get this error:
The action 'show' could not be found for LearnController
Here is my controller:
class LearnController < ApplicationController
def more
end
end
and in routes i do this:
resources :learn
I know that resources creates all the show, edit, index and all that but how do I make it so only the actions i create are created in the routes?
As you mention, resources :learn will create a bunch of routes according to the resourceful convention.
If you don't want those, don't use resources in your config/routes.rb file. Instead, use get, match, and friends to define your routes manually. E.g.
get 'learn/more'
In my UserController I have:
def join
end
I have a join.html.erb in my /views/user/ folder.
My routes has a :
resources :user
When I go to:
http://localhost:3000/user/join
I get:
The action 'show' could not be found for UserController
Re: why isn't the join action found?
To answer your specific question, what's happening is that you want to have an action "join" for your User model.
Your problem is that you haven't defined a route matching the url http://localhost:3000/user/join
The line resources :user in your routes file only defines routes for the seven standard rest verbs/actions:
index, new, create, show, edit, update, destroy
See: http://apidock.com/rails/ActionController/Resources/resources
Added: to fix, you'll need to add an explicit or generic route. Routing docs
Added: Re: why am I seeing the error message re show? To be ultra-precise, the route selector "GET /usr/:id" (created by your resource call) is being used to select the SHOW action for the User resource. The :id value is being set to "join". Since you don't have a Show method defined in your controller, that's the error that you're seeing.
You're using resources, but have a non-REST action, so you need to add the join action to the route with the appropriate HTTP verb:
map.resources :users, :member => { :join => :get }
Place:
def show
end
in your UserController.
To be certain:
app/controllers/users_controller.rb
def join
end
app/views/users/join.html.erb
config/routes.rb
resources :users