Validations & Filters


Collapse Content

Now that signed-in users are associated with the Posts they create, let's make sure only signed-in users can create posts. This will consist of a few steps across the MVC structure:

  1. Add code to the model to make sure posts cannot be saved without a user
  2. Add code to the controller so certain actions can only be accessed by signed-in users
  3. Add code to the view so the form links are only displayed when appropriate.

Model

First, can you add a validation to ensure that every post has a user_id and content?

Model Code

Validation Errors

Validations make it easy to keep track of any errors saving an item. You can access

p = Post.new
p.errors
=> #<ActiveModel::Errors:0x007fec4f278218 @base=#<Post id: nil, content: nil, created_at: nil, updated_at: nil, user_id: nil>, @messages={:user_id=>["can't be blank"], :content=>["can't be blank"]}>

These errors are easily displayed in the form to the user. Try creating a new post without any content. The page will be re-rendered and the field that caused an error will be highlighted with an error message:

Controller

As mentioned earlier, you can use the Rails before_action method to control access to certain methods. Let's use before_action with the Devise authenticate_user! method to prevent non signed-in users from accessing certain actions:

controllers/posts_controller.rb

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
  #...

If you now navigate to 'posts/new' when not signed in, you will be redirected to the sign-in page. Once you sign-in, you'll be helpfully redirected to the page you were trying to visit.

View

Since non signed-in visitors cannot post new content, we may not want to display the "New Post" button to them. You can wrap it with a Devise method to only display it to signed-in users:

views/posts/index.html.erb

<% if user_signed_in? %>
  <%= link_to 'New Post', new_post_path %>
<% end %>
Contact Us
Sign in or email us at [email protected]