Adam O'Grady

Rails Forum Skeleton: Part 3

Following on from my last tutorial where we set up users and primitive authentication/access control, we’re going to work on fleshing out the forum aspect further. Let’s start by allowing login and identifying users by a separate value, a “username”.

I’ve added username as an attribute to the User model, to do that run rails g migration AddUsernameToUsers username:string then enter rake db:migrate. To get it working as the identifier for accounts you’ll need to go to config/initializers/devise.rb and find the line that begins with config.authentication_keys = , make sure it’s uncommented and set it to [ :username ] (if that’s your attribute name for identifying users). You’ll also need to go to the User model and add validates :email, uniqueness: { case_sensitive: false }, presence: true to make sure the email is still a unique key in your database. Later versions of Rails also use strong parameters and so to allow username through when performing functions you’ll need to add the following to app/controllers/application_controller.rb down before the end keyword:

before_action :configure_permitted_parameters, if: :devise_controller?


def configure_permitted_parameters
  devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation, :remember_me) }
  devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :remember_me) }
  devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :email, :password, :password_confirmation, :current_password) }

Now you’ll need to run rails generate devise:views which sets up all the views used by the Devise gem into our app/views folder so we can modify them if needed. Open up app/views/devise/registrations/new.html.erb and add the following under <%= devise_error_messages! %>:

<div><%= f.label :username %><br />
<%= f.text_field :username, autofocus: true %></div>

Also remove the , autofocus: true from the email field section. Open up app/views/devise/registrations/edit.html.erb and under the devise error messages line again add:

<div><%= f.label :username %><br />
<%= f.text_field :username, autofocus: true %></div>

Again, remove the , autofocus: true from the email field. Next you’ll need to bring up app/views/devise/sessions/new.html.erb and change the two lines of the form pertaining to email to the following:

<div><%= f.label :username %><br />
<%= f.text_field :username, autofocus: true %></div>

At this point, you should now have the ability to log in via username. Since the username property is on the User model, it’ll also be available when you retrieve user records, so you can modify app/views/discussions/show.html.erb and add the following lines before the post content div:

  <% if post.user != nil %>
    <% if current_user == post.user && post.user != nil %>
    <% else %>
      <%= post.user.username %>
    <% end %>
  <% else %>
    [User Deleted]
  <% end %>

What this does is create an element before the post content that displays who the user is, indicates you (the currently logged in person) as the user or advises that the user account has been deleted. You can add a similar thing to app/views/discussions/index.html.erb for each discussion to show who created it. The creator’s username is accessible via “discussion.user.username” inside the discussions for each loop.

We can also add Gravatar (a popular internet avatar platform) support by adding gem 'gravtastic' as a new line on the bottom of our Gemfile and then run bundle install to install it and add the following two lines to the top of your User model (under the heading):

include Gravtastic

To place a gravatar, add the following code while substituting with your user variable as necessary; <%= image_tag [USER VAR].gravatar_url %>. Try putting this in another <div></div> above the username section in app/views/discussions/show.html.erb. All you need to do now is restart the Rails server and it should work.

Thanks for following along so far and I hope your forum is starting to look more well-rounded.

Feel free to check out my final thoughts about this tutorial series as well.