I've come across a very strange problem with Rails 5. I've two controllers, first as users_controller
and second as api/v1/users_controller
. Both these controllers have a register
action. I am trying to post a form to both these controllers. This form is created as below,
<%= form_tag('v2/register/user', {id: "add-user-form", class: "jiffle-form", role: "form"}) do%>
#form body
<%= submit_tag("Resigter", data: {i18n: "register"}, class: "btn btn-lg btn-block btn-blue", id: "add-user", type: "submit") %>
<% end %>
Routes,
post "register" => "users#create", :as => "user_registeration_submit"
post "v2/register/user" => "api/v1/users#create"
When I use /register
url to submit the form it gets processed successfully. However, when I use v2/register/user
url to submit the form I am getting Can't verify CSRF token authenticity
error.
Params
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ADNTIp9alRB/ujRhkoqNuDkzdW6ANfcl/MbPjGLwVd6nwVuG5oi+uVhE9MeZo+1MeyKLbwZYNV31Vy/VH3M2bg==", "sfdc_token"=>"",
"email"=>"[FILTERED]", "first_name"=>"kjl", "last_name"=>"jk", "contact_no"=>"894892849", "company_name"=>"j", "title"=>"kj",
"internal_366vagan2"=>"", "consent"=>"true",
"commit"=>"Register"}
When I use ajax to submit the form to api/v1/users_controller
with X-CSRF-TOKEN header in the request it works fine.
Where do I make a change to get my api/v1 controller to work?
You can simply write in application_controller.rb
protect_from_forgery with: :exception, unless: -> { request.format.json? }
And set default format will be json in routes.rb file
But better approach:
In your case, you have to create two namespaces, one for handing API response and second one for FORM handling. Use namespaces in routes.rb file accordingly. And also two different base controller accordingly that inherits from ApplicationController.
For API
class Api::V1::ApplicationController < ApplicationController
protect_from_forgery with: :exception, unless: -> { request.format.json? }
end
And set default format will be json in routes.rb file
resources :tasks, defaults: {format: :json}
For FORM View
Use bydefault settings, or
class Admin::AdminController < ApplicationController
protect_from_forgery with: :exception
end
#In this case, comment it from main application_controller.rb file:protect_from_forgery with: :exception
Note: here Admin and Api are two namespaces. And routes.rb file will look like:
#For admin
namespace :admin do
end
#For Api
namespace :api do
scope module: :v1 do
end
end
Hope it will work :)