Strong Parameters

Our new Active Record models behave mostly the same as before, but with a couple of exceptions.

Handling params

One glaring issue is that if we try to create a post right now, we get this:

ActiveModel::ForbiddenAttributesError in PostsController#create

This is because Active Record models distrust params by default. There are security reasons for this, but we obviously want to allow some params to be used, so we'll have to specify which ones to permit in our post controller:

### app/controllers/posts_controller.rb ###

class PostsController < ApplicationController

  # ...

  def create
    @post = Post.new(post_params)

    # ...
  end

  def update
    if @post.update_attributes(post_params)
      # ...
    end
  end

private

  # ...

  def post_params
    params.require(:post).permit(:title, :body, :author)
  end
end

Here we just create a post_params private helper method and use it to grab the params we want. We then use it in the calls to our Post model in the create and update actions.

The params.require(:post) call makes sure that there is something at params[:post]. Subsequently, .permit(...) grabs the pairs out of that params[:post] hash that we want and allows them to be passed to Post.

A similar params method will be needed in the comments controller. Be sure to add that in as well so that your app works as intended. Additionally, you will need to change your create action for comments_controller.rb

def create
  @comment = @post.comments.build(comment_params)
  if @comment.save
    # ...
  else
    @post.reload.comments
    # ...
  end
end

When comment validation fails, even though the comment is not saved in the database, it is still being associated with the current post in memory. This will raise an exception when rendering the show.html.erb because of its dependency on comment.id where our invalid comment will have an id of nil. Because of the way we wrote our code, we are grabbing all the comments associated with the current post in memory rather than directly from the database. To solve this, we need to add @post.reload.comments during comment validation failures to make sure our current post is synced with the database.

More Resources

For more on these topics, check out: