Following on from my [last tutorial]({{< relref "/dev/rails-forum-skeleton-part-2.md" >}}) 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? protected 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) } end 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! %>`:
<%= f.label :username %>
<%= f.text_field :username, autofocus: true %>
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:
<%= f.label :username %>
<%= f.text_field :username, autofocus: true %>
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:
<%= f.label :username %>
<%= f.text_field :username, autofocus: true %>
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:
User: <% if post.user != nil %> <% if current_user == post.user && post.user != nil %> You! <% 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](https://en.gravatar.com/) (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 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 `
` 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]({{< relref "/dev/rails-forum-skeleton-thoughts.md" >}}) as well.