Reputation: 28622
I'm totally new to Rails and I'm playing with it. Now I'm trying to understand the strong parameter
feature introduced in Rails 4. Below is my code:
class PostsController < ApplicationController
def index
end
def show
end
def create
p = Post.new(create_post_params)
p.save
redirect_to p
end
def new
end
private
def create_post_params
params.require(:post).permit :title, :body
end
end
Beside the controller, I also have a Post model with a title
and a body
. My question is what is this :post thing in params.require(:post).permit :title, :body
? I write it as :post, is it because I'm currently inside the PostsController
? Or I'm reading the properties of a Post
?
Based on gdpelican's answer, if my new.html.erb
is like this:
<h1>Create a post</h1>
<%= form_for :post, url: posts_path do |f| %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
<p class="help-block">Please type the title of the post</>
</div>
<div class="form-group">
<%= f.label :body %>
<%= f.text_area :body, class: "form-control", rows: 5 %>
<p class="help-block">Please type the body of the post</>
</div>
<%= f.submit class: "btn btn-primary" %>
<% end %>
It's the :post part in <%= form_for :post, url: posts_path do |f| %>
determines that I should use :post in params.require(:post).permit :title, :body
, right?
Upvotes: 0
Views: 374
Reputation: 568
It is the name of the JSON wrapper of your form values.
The form will typically wrap the form parameters like so:
{
post: {
title: "Title",
body: "Body",
}
}
When using something like form_for @post
In essence, params.require(:post).permit(:title, :body)
is saying two things:
The parameters in form_for
are what affect how your parameters are wrapped.
Generally, the name of the controller matches the name of the form parameters, so in most instances it's a safe assumption that a 'BooksController' will accept form parameters in a 'book' field.
Upvotes: 2
Reputation: 8836
Your parameters (typically) look like this
{"utf8"=>"✓", "authenticity_token"=>"...", "post"=>{"title"=>"My title", "body" =>"Body of my Post"}}
When you require a specific key from the parameters (for example post) Rails will throw an error if the hash it was passed doesn't have "post"=>{....}
, then once it passes that check it permits the allowed keys and returns only the parameters nested under "post" hash allowed. To copy the api docs examples
params = ActionController::Parameters.new({
person: {
name: 'Francesco',
age: 22,
role: 'admin'
}
})
params.require(:person).permit(:name, :age)
=>{"name"=>"Francesco", "age"=>22}
So after your strong params check, the return is a hash of :post
parameters that you have allowed.
EDIT: To answer your second question.
That is one way of thinking about it. Your form syntax (form_for :post
) is creating the post
hash with the attributes nested inside, and sending it as part of the overall parameters hash. And your params.require(:post)
is taking the entire params, and finding only the hash key it wants (post
) and then permitting the keys that are inside the post hash.
Upvotes: 2