Search code examples
ruby-on-railsruby-on-rails-4strong-parameters

Understanding of Rails 4's strong parameters


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?


Edit

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?


Solution

  • 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.