可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In Rails I can automatically create a set of routes for CRUD actions using resources
in the routes file.
This creates index
, new
, create
, edit
, show
, update
and destroy routes.
I understand the general flow of how these routes work and usually when a route is called a model object is created according to the parameters passed into the corresponding action and the corresponding view is created or the client is redirected to another specified action.
Both the new
and edit
views can use the same _form
partial to update the model object in their respective actions. However I am struggling to understand how the client is redirected to another action afterwards.
For example in the new
action the client is redirected to the create
action and the model object that was updated in new
is passed to create
as a parameter. I don’t understand how this is happening since no redirect is specified and I cannot see how the model object is turned into a parameter.
def new
@article = Article.new
end
def create
@article = Article.create(article_params)
redirect_to(article_path(@article.id))
end
_form Partial:
<%= form_for(@article) do |f| %>
<ul>
<% @article.errors.full_messages.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
<p>
<%= f.label( :title ) %><br>
<%= f.text_field( :title ) %>
</p>
<p>
<%= f.label( :body ) %><br>
<%= f.text_area( :body ) %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
回答1:
OOP
The bottom line answer to your question is that Rails is object orientated (by virtue of being built on top of Ruby). This is very important, as it means everything inside Rails should be based around objects:
This leads me to the routes - the resourceful
nature of Rails' routes is down to the same idea, that you need to work with objects in your application - hence the resources
directive providing 7 key actions to manipulate those objects
To fully understand Rails, you really need to look into how it works with objects, specifically how they interact with each other
Redirect
To answer your question regarding the redirect
, the simple answer is that Rails doesn't "redirect" to any action specifically
Remember, Rails is stateless - it does not persist data through requests - it only has the data which you either initialize at the time, or have sent it
What you're confused about is how some of the Rails actions seem to be sending your requests to the appropriate "request" action. The answer to this lies in the helpers / methods you use, specifically form_for
form_for
form_for builds forms from their ActiveRecord objects.
Therefore, if you perform the following:
#app/controllers/your_controller.rb
Class YourController < ActiveRecord::Base
def new
@model = Model.new
end
end
This will give Rails the knowledge that it's loading a new
object, and therefore will use the form_for
method to send the request to the create action
If you used form_tag
, you would not get a redirect to the create
action -- that's the magic of Rails -- it's been built to accommodate objects
回答2:
when you hit your new action in routes by /articles/new
. It render your form and if you inspect that form you'll see the html generated by your form_for is like this
<%= form_for @article, html: {class: "nifty_form"} do |f| %>
<%= f.text_field :title %>
<%= f.text_area :body, size: "60x12" %>
<%= f.submit "Create" %>
<% end %>
and its HTML would be
<form accept-charset="UTF-8" action="/articles/create" method="post" class="nifty_form">
<input id="article_title" name="article[title]" type="text" />
<textarea id="article_body" name="article[body]" cols="60" rows="12"></textarea>
<input name="commit" type="submit" value="Create" />
</form>
So when you hit your submit button your form takes you to create method of article with form parameters
Same form in edit action
when you hit your edit action articles/edit/1
. If you look at your edit action it would have
def edit
@article = Article.find(params[:id])
end
So this renders your form with Article which has id 1
And the same form will have html which will look like this
<form accept-charset="UTF-8" action="/articles/1/update" method="patch" class="nifty_form">
<input id="article_title" name="article[title]" type="text" />
<textarea id="article_body" name="article[body]" cols="60" rows="12"></textarea>
<input name="commit" type="submit" value="Update" />
</form>
Notice your action is changed in html because in your edit action you have initialized @article and your form generates url according to your initialized variable
回答3:
Well, it does not use redirect. It directs you to the exact method with the html form action.
To clarify it:
When you are in "/articles/new". Rails will dispatch you to Controller#new action.
And, if the _form partial is implemented with Form Helpers by using form_for
<%= form_for @article do |f| %>
<% end %>
It will generate html form, like so:
<form accept-charset="UTF-8" action="/article" method="post">
</form>
As you can see, the form action attribute is "/article"
which is mapped to your CRUD actions in the resource.
Then, after you click submit button in the form, the data in the form will be sent to create
action as specified in the form tag action attribute.
And the exact same partial _form (form_for) code we have used, can also be used to edit an Article. If @article record is already existed in the table and the form_for will yield this html form instead:
<form action="/article/1" class="edit_article" id="edit_person_1" method="post">
</form>
And, you can notice that action attribute now will direct you to update
action in the CRUD.
Therefore, form_for
reflects knowledge about the resource it deals with or Record Identification like Rails document said (http://guides.rubyonrails.org/form_helpers.html#2.3)
Hope this helps you understand it :)