Welcome to Post 3! We are likely going to need at least two to three posts just to customize devise.

The first thing I want to do is add the FriendlyId gem, so we can create nice looking user and post urls, such as: https://yourdomain/users/your-name.

Customizing Devise

# Gemfile add: 

gem 'friendly_id', '~> 5.1.0' # Check for the latest version on Ruby Gems
bundle install
# Next create the configuration file with:
rails generate friendly_id
# Now let’s add FriendlyId to our user and post models:
rails g migration add_slug_to_users slug
rails g migration add_slug_to_posts slug
rails db:migrate
# Now open app/models/user.rb and add:
 extend FriendlyId
   friendly_id :uniqueslug, use: :slugged 

  def uniqueslug 
# The unigueslug method above is so that we can call FriendlyId on two attributes - first_name and last_name, which we created earlier.

# Now open app/models/post.rb and add:
 extend FriendlyId
   friendly_id :title, use: :slugged # Our post title will be used as the url. 

Posts with Friendly ID's

Now we need to edit our app/controllers/posts_controller.rb file for friendlyId. We need to add the slug attribute, and we also need to update how we find posts.

# Under the private method section add:

 def set_psot
   @post = Post.friendly.find(params[:id]) # Added friendly before find!

 def post_params
  params.require(:post).permit(:title_tag, :meta, :tittle, :body, :cover_image, :slug) # Added slug

Devise Lockable

Since we added the lockable function for devise, we need to add this to our user model file. We will also add some validations while we are there.

# Open app/models/user.rb and add update the current devise attributes to include lockable. We will also set the min and max length for passwords

devise :database_authenticable, :registerable, :recoverable, rememberable, :trackable, :validatable, :lockable, password_length: 10..70

# Now let’s add some password requirements:

validate :password_complexity

 def password_complexity
    if password.present? and not password.match(/\A(?=.{8,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[[:^alnum:]])/)
      errors.add :password, "must include at least one lowercase letter, one uppercase letter, and one digit"

# Add validations for the first and last name length

validates :first_name, presence: true,
length: { minimum: 2, maximum: 25 }

validates :last_name, presence: true,
length: { minimum: 2, maximum: 25 }

# For more advanced security you can use the devise security gem as well https://github.com/phatworx/devise_security_extension

Let’s now add some basic validations to the post model

# Open app/models/post.rb and add:
validates :titletag, presence: true, length: {minimum: 50, maximum: 60 }
validates :meta, presence: true, length: {minimum: 150, maximum: 320 }
validates :title, presence: true
validates :body, presence: true

Now we are almost ready to create some users! However, let's do a few things first

# Open config/initializers/devise.rb and make the following edits:

# ==> Mailer Configuration
config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
# Change this to:
config.mailer_sender = hello@deviseblog.com # you could put anything here...’

# Now we are going to uncomment a few things and make sure they are set:
# ==> Configuration for :rememberable
# The time the user will be remembered without asking for credentials again.
  config.remember_for = 2.weeks

# ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again. Default is 30 minutes.
  config.timeout_in = 30.minutes

# Now configure lockable:
# ==> Configuration for :lockable
# Defines which strategy will be used to lock an account.
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
# :none            = No lock strategy. You should handle locking by yourself.
  config.lock_strategy = :failed_attempts

  # Defines which key will be used when locking and unlocking an account
  config.unlock_keys = [ :email ]

  # Defines which strategy will be used to unlock an account.
  # :email = Sends an unlock link to the user email
  # :time  = Re-enables login after a certain amount of time (see :unlock_in below)
  # :both  = Enables both strategies
  # :none  = No unlock strategy. You should handle unlocking by yourself.
  config.unlock_strategy = :both

  # Number of authentication tries before locking an account if lock_strategy
  # is failed attempts.
  config.maximum_attempts = 15

  # Time interval to unlock the account if :time is enabled as unlock_strategy.
  config.unlock_in = 1.hour

  # Warn on the last attempt before the account is locked.
  config.last_attempt_warning = true

Let's also set up how we are going to handle regular users versus admins

We are going to use enum's for this, which you can learn more about here.

# Open the user model file again and add:
 enum role: [:user, :admin, :vip] # You can call your roles whatever you want. User will be 1, Admin will be 2, and VIP will be 3.
 after_initialize :set_default_role, :if => :new_record?

  def set_default_role
    self.role ||= :user

Customizing Devise Notices & Alerts

Just a quick note: if you want to change the default messages for devise alerts and notices, open config/locales/devise.en.yml and simply edit any message you want to change.

Let’s create some users!

# in the terminal run:
rails c
# User 1
User.create!(first_name: "Fox", last_name: "Mulder", email: "fox@xfiles.com", password: "Xfiles1993*", password_confirmation: "Xfiles1993*")
# User 2
User.create!(first_name: "Dana", last_name: "Scully", email: "dana@xfiles.com", password: "Xfiles1993*", password_confirmation: "Xfiles1993*")
# User 3
User.create!(first_name: "Walter", last_name: "Skinner", email: "walter@xfiles.com", password: "Xfiles1993*", password_confirmation: "Xfiles1993*")

Now let's assign some roles to these users

# in the terminal run:
rails c
# Let's create a fourth user inside the console for demonstration purposes
User.create!(first_name: "Test", last_name: "Testing", email: "test@test.com", password: "Xfiles1993*", password_confirmation: "Xfiles1993*")
# Now lets check this users role with:
u = User.last
=> user # this is what we wanted, because we set the default role as user.
# Now lets make this user an admin with:
# Now run u.role again and it will be:
=> admin

Awesome, now try to make Fox Mulder an admin, and Dana Scully a very important person.

Let’s commit our work

git add .
git commit -m Added the FriendlyId gem, and added validations for users and posts
git push origin master
git push heroku master
heroku run rails db:migrate
Click here to view part 4. Or click here to go back to part part 2.