Reputation: 4380
I'm not completely new to Ruby on Rails but it is not my most proficient framework so I was hoping someone could help me wrap my head around some code I'm trying to understand.
controller:
def new
@biz = Business.new
end
def apply
@biz = Business.new(business_params)
token = SecureRandom.hex(4)
@biz.verify_token = token
if @biz.save
message = @biz.sentMessages.new
message.send_verify_email
redirect_to waiting_verification_path
else
render 'new'
end
end
routes:
get 'apply', to: 'businesses#new', as: 'apply'
post 'apply', to: 'businesses#apply', as: 'applied'
view:
= simple_form_for @biz, url: apply_path, html: {autocomplete: "off"} do |f|
I understand that the first line of the routes directs a request at /apply
to the new
action in the controller which creates a new business object and renders the new
view, which I have included a snippet from. This snippet includes the form action which directs a successful submission to the apply_path
.
My understanding indicates that this apply_path
is a named helper for the first routes line when I believe it should be directed to the second line, whose helper would be applied_path
, and would then be handled by the apply
action on the controller.
What is really causing me confusion is that this functionality works. So the submission is in fact being routed to the second routes line and being handled by the apply
action in the controller. If you could explain how this is happening I would appreciate it tremendously. Thank you.
Upvotes: 2
Views: 87
Reputation: 4603
The generated form will look like
<form action="/apply" method="post" autocomplete="off" class="simple_form new_business">
Note the method
attribute: Because @biz
is a new record, SimpleForm knows this should be HTTP POST'ed to the url
specified (AFAIK persisted records will still create a method="post"
on the form, but an additional hidden field with name="_method"
and value="put"
is inserted).
Since both route helpers, apply_path
and applied_path
, just generate the string '/apply'
, it does not matter which URL you define in your form. This should equally well work:
= simple_form_for @biz, url: applied_path, html: {autocomplete: "off"} do |f|
When you submit the form, your browser creates an HTTP request, like this:
POST /apply HTTP/1.1
<header information>
<post body>
and Journey (the Rails router module) will take the information POST
+ /apply
to find the route to businesses#apply
.
To make the route definition a little more concise, you could rewrite it as
scope as: :apply do
get '/apply', to: 'businesses#new'
post '/apply', to: 'businesses#apply'
end
Upvotes: 0
Reputation: 16110
The reason this is working is that you have two named routes that map to the same path. applied_path
is /apply
, and apply_path
is /apply
. These two named paths are IDENTICAL. The difference comes when the form performs a POST
to /apply
, it sees a POST
and immediately goes to the second route. While a GET
to that same /apply
path will go to the first route.
On this note, you only really need to name one of the routes and just use that name everywhere. This is why, when you declare a resource in your routes file:
resources :users
You end up with a "POST /users" and a "GET /users" path which routes to users#create
and users#index
respectively, based on what kind of request was sent - BUT you only have one users_path
named route, which always returns "/users"
Upvotes: 0
Reputation: 14900
The line
= simple_form_for @bix, url: apply_path
generates something like
<form action="/apply" method="post">
..
</form>
POST is the default method on forms, so when the form is then POST-ed
Rails looks at the routes.rb file and sees a match on this line.
post 'apply', to: 'businesses#apply', as: 'applied'
If however you had done it like this
= simple_form_for @bix, url: apply_path, method: :get
The form is submitted via GET
and then Rails would find a match on the first line in routes.rb.
get 'apply', to: 'businesses#new', as: 'apply'
It doesn't matter what the name of the routes_helpers are, all that matters is the generated url. I hope that clears thing out, if not, just ask for more clarification.
Upvotes: 1