- Intro to Fast Rails Development
- Rails Quick Start
- Rails Scaffold
- Scaffold Tour I - Resources
- Scaffold II - Forms
- User Post Relationship
- Validations & Filters
- Correct User
- Adjusting the Pages
- Header Adjustments
- Simple Twist
- 1000 Words
- Live Site on Heroku
Build a quick blog platform with Rails. (Beta tutorial.)
Validations & Filters
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:
- Add code to the model to make sure posts cannot be saved without a user
- Add code to the controller so certain actions can only be accessed by signed-in users
- 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?
class Post < ActiveRecord::Base
validates :user_id, presence: true
validates :content, presence: true
belongs_to :user
end
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 %>