How to have custom POST requests - ruby-on-rails

I have a WelcomeController which for the moment only has the action GET#index which does nothing (the view renders a welcome message) and is also the root path.
In this view, I want to have two buttons to perform action1 and action2. I've managed to get the result I want with action1 button by doing this:
class WelcomeController < ApplicationController
def index
end
def action1
... #code
end
end
views/welcome/index.html.slim
h1 = "Welcome"
br
= form_tag url: welcome_index_path do
- if user_signed_in?
= submit_tag "Action1"
And in routes.rb:
get 'welcome/index'
post '/welcome/index', to: 'welcome#action1'
I wanna add now the second button in a similar way, but when I click on it, it performs Action1 (I assume it's because the re-routing of post request for welcome/index in routes.rb.
How do I properly do this, so that I can have as many actions that send POST requests as I want?

You may go this document to learn more about routing in rails.
In this case, you may define your routes.rb like this:
resources :welcome, controller: 'welcome', as: 'welcome', only: [:index] do
collection do
post 'action_1'
post 'action_2'
end
end
Then you view will be:
= form_tag url: welcome_action_1_path do
= submit_tag "Action1"
= form_tag url: welcome_action_2_path do
= submit_tag "Action2"

This is more about routing. Check Rails guide on routing, which will help you a lot.
http://guides.rubyonrails.org/routing.html
For action1, you probably want to set a different route.
get 'welcome/index'
post 'welcome/action1', to: 'welcome#action1'
That means an HTTP POST action to url 'welcome/action1' will map to action1 method in welcome controller.
You can keep on adding these.
post 'welcome/action2', to: 'welcome#action2'
You can also use other HTTP methods. Different HTTP methods to same url can be routed to different methods.
get 'welcome/action3', to: 'welcome#action3_get'
post 'welcome/action3', to: 'welcome#action3_post'
patch 'welcome/action4', to: 'welcome#action4'
delete 'welcome/action5', to: 'welcome#action5'
In addition, you can also set an alias for that route, similar to welcome_index_path, which is, after all, a path generated by rails helper that maps to get 'welcome/index' by default.
post 'welcome/action6', to: 'welcome#action6', as: 'welcome_action6'
Then you can use welcome_action6_path in your form tag too.

Related

Modify routes in rails

I'm a new user of rails so it's complicated to understand how the routes.rb works! So I try to modify a route, I got a path that look like this:
user/:id/edit but i want that the id not appear in the path.
I try to use this method :
get '/users/:id/edit', to: 'users#edit', as: 'users/edit'
but it changes nothing. In my routes.rb i got :
resources :users, only: [:create, :new, :show, :edit]
Someone know how to do this? I already take a look at this guide
If you already take a look at guides, do you read about singular resources?
Sometimes, you have a resource that clients always look up without
referencing an ID. For example, you would like /profile to always show
the profile of the currently logged in user. In this case, you can use
a singular resource to map /profile (rather than /profile/:id) to the
show action:
resource :geocoder
creates six different routes in your application, all mapping to the Geocoders controller:
GET /geocoder/new geocoders#new return an HTML form for creating the geocoder
POST /geocoder geocoders#create create the new geocoder
GET /geocoder geocoders#show display the one and only geocoder resource
GET /geocoder/edit geocoders#edit return an HTML form for editing the geocoder
PATCH/PUT /geocoder geocoders#update update the one and only geocoder resource
DELETE /geocoder geocoders#destroy delete the geocoder resource
If you have taken,
resources :users
Now change this route as follows,
get '/users/edit', to: 'users#edit', as: 'users_edit'
Now in your view file where you have edit link, change the link to,
<%= link_to 'Edit', users_edit_path(:id => user.id) %>
Now this links to the edit action of users controller with an id parameter.
Now, in the users controller file,
class UsersController < ApplicationController
def edit
// params[:id] will be the ID that you sent through the view file.
#user = User.find(params[:id])
end
end
Thats it, you are done with your custom route, now the route will be users/edit instead of users/:id/edit

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.

Rails 4 match all routes for one controller

I have a controller with a number of static pages and I would ideally like to route them all with a wildcard.
Is it possible to do something like the following?
get 'static/:action'
Why don't you just use the show action:
#config/routes.rb
resources :static, param: :page, only: :show #-> url.com/static/:page
#app/controllers/static_controller.rb
class StaticController < ApplicationController
def show
render "#{params[:page]}"
end
end
This way, you can pass the "page" directly through the link and have it all handled by Rails:
<%= link_to "About", static_path("page") %>
You probably need something like get 'static/:action', to: 'static#show' and then in your StaticController show action render the correct static page based on the params[:action] parameter.
See http://guides.rubyonrails.org/routing.html#defining-defaults for more.
You can route something like
get '*path', to: 'static#show'

Referring to a nested resourse

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

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,

Resources