Date Formatting and Customizing Devise

This week will focus on formatting the rails app to be more user friendly. If this is your first time to this site, please see the first post on making your owns rails blog. Before we start with this weeks topics I made some basic CSS and formatting changes that can be seen here. Currently the blog displays dates in RFC format and only shows the authors email. This week you’ll use Rails I8ln tools to build custom date formatting. We’ll also extend Devise, allowing users to login with a user name.

Custom Date Formatting

There are two main theories to Date Formatting. Building a time_format initializer or adding date formats to your locales file. Since date formats differ between regions it makes sense to place these formats in your locales file.

Open up config/locales/en.yml, app/view/posts/show.html.erb, and app/view/posts/index.html.erb and make these changes. In locales file, the format named “default” will be used if no format is specified. In the view file, those are L’s that have been added prior to the dates. L is a default rails helper method for localize and will apply the localization for that data in our case a timestamp. You can add as many differing formats as you’d like. You can call these by using the following code

<%= l Time.now, :format => :awesome %>

A cheat sheet of all ruby date formats can be found here. If you would like more information on locale files, Ruby on Rails has a good guide on it.

Usernames

Adding usernames is a breeze with Devise. The first step to is create a migration to add the column.
$rails g migration addUsernameToUser username:string
Open up the generated migration and make these changes then run the migration.
Since we plan to allow users to login using their username we’ve made it a unique key, the database will not allow more than 1 User to have the same username. Now that the column is created, modify the User model to allow editing and validation of username. We will also make sure that Devise is validating data in the forms. You can see the changes here, user.rb

Now that our model and database are set to handle usernames, we have to make sure our views can handle them. To do this we need to extend the default Devise views. Run the following commands and then edit the files as seen here.
$ rails generate devise:views
For more information about this as well as how to let user recover their passwords using username or email please see the Devise wiki.
Now that we can edit, login and register with usernames, lets display them on our page. Edit post show and post index templates as seen here.

Check in next week were we will add comments to the posts.

Adding Authorization Using Devise

This will cover how to use Devise as your user authentication system. In previous posts I’ve used AuthLogic which is a good solution, I just find Devise simpler to use and implement. This will extend from my article Rails 3 Blog Tutorial. I’d highly suggest going through that tutorial, or you can run these commands.

git clone git@github.com:baileylo/blog.git
git checkout -b blogCreated 0ba92371c2998caf362827987a82050708e9cd25

First add devise to your gemfile, gem “Devise”. Then run the follow commands:

$ bundle install
$ rails generate devise:install

This will install the Devise gem and set up the Devise modules. You will be prompted for 3 steps:

Some setup you must do manually if you haven't yet:

  1. Setup default url options for your specific environment. Here is an
     example of development environment:

       config.action_mailer.default_url_options = { :host => 'localhost:3000' }

     This is a required Rails configuration. In production it must be the
     actual host of your application

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root :to => "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

Do step 1, step 2 and 3 should already be done. Once you have completed these steps run:

$ rails generate devise user

Open up your user model(app/models/users.rb). You will see a comment at the top listing possible devise modules. You can add and remove these as you wish. For this tutorial we’ll only use: database_authenticatable, registerable, recoverable, rememberable, trackable. Save the changes, and run:

$ rake db:migrate
Now if you run “rake routes” you will see a series of /users/ routes setup automatically by Devise. Open up your application template, app/views/layout/application.html.erb and add the following code:

<div class="user-auth-nav" style="float:right">
  <% if user_signed_in? %>
  <%= link_to('Edit registration', edit_user_registration_path) %> | 
  <%= link_to('Logout', destroy_user_session_path) %> 
  <% else %>
  <%= link_to('Login', new_user_session_path)  %> | 
  <%= link_to('Register', new_user_registration_path)  %>
  <% end %>
</div>

diff

Restart your rails server, and then reload your page. You should see in the top right Login and Register links. Feel free to create an account and play around with Devise’s built in authentication and user validation.

Now we need to associate a specific author with a specific post. To do this will use another migration:

$ rails generate migrate addUserIdToPosts user_id:integer
$ rake db:migrate

Rails migration generator will automatically read the migration name and realize that we’re adding the UserId column To the Posts table. Now we need to make the relationships between the models in ruby. Open up the user model(app/models/user.rb) and add “has_many :posts” within the class definition. Now open the posts model (app/models/post.rb) and add “belongs_to :user” within the class definition.
diff

So far now we’ve created user authentication system and added user to a post. Open your posts controller (app/controllers/posts_controller.rb) and add the following line at the top of your class, but inside the class definition
before_filter :authenticate_user!, :only => [:edit, :update, :destroy, :create, :new]
This will apply Devise’s built in function authenticate_user! When the actions edit, update, create, new, and destroy are called. It will effectively require the user to be logged in to access these actions.

Prior to a post being saved, we’re going to want to set the “poster” to be the user who is currently signed in. Devise provides the current_user helper which allows you access to the logged in user’s User object. Change the “create” action in the posts controller to look like this.

@post = Post.new(params[:post])
@post.user = current_user

diff

This will assign the currently logged in user as the user for the post. Lets clean up the views a little big. Change your posts index.html.erb and show.html.erb files to look like this, app/views/posts/.
diff

You may be getting error that reads: “undefined method `email’ for nil:NilClass“. These blogs were posted prior to having added the user migration. You can add an if statement to skip the user data when a Post doesn’t have a related User Object. But lets make a migration, run the following command
$ rails g migration insertUserInAllPosts

Open up the generated migration, and make the following changes . We named the migration “insertUserInAllPosts”, the name is up to you. It is nice to have descriptive names for migrations; in the future you will waste less time figuring out what the migration does if it has a good name.
diff

You may have noticed that we have removed the links to edit posts for other users, but they can still edit posts if they go directly to the url. To fix this we’ll use another “before_filter”. Open up the posts controller, app/controllers/post_controller.rb, and make the following changes:
diff

Now you have a full authorized blog. Come back next week to see user customizations.

Rails 3 Blog Tutorial

This tutorial will cover the creation of a personal blog using Ruby on Rails 3. This tutorial assumes that you have Sqlite3, and Rails gem installed. There will be other applications used but their installation is explained as is needed.

The Blog:
First lets create our rails application and come up with some basic starting blocks for our blog.
$ rails new blog
$ cd blog
$ rails generate scaffold post title:string body:text
$ rake db:migrate
$ rails -s

The first two commands create the base rails framework. The next command is where you see a lot of the benefit of using ruby on rails. It automatically created the migration files, model files, controller files, and view files for our new database object called “Post”.
Migrations are how rails tracks schema changes in your database. You can migrate the database up to a latest migration or roll down to a previous migration. Rake db:migrate is the command to make the schema changes for the latest migration. Rails -s creates a simple webbrick server; this server is good for development, but not production.

You should now be able to goto localhost:3000 where you will be greeted by a friend rails page. Of course you probably don’t want your users to see this page so remove public/index.html.erb and add a new route, ‘root :to => “posts#show” to your configs.rb, seen here.

Once you reload your homepage you should see the friendly rails scaffolding. Feel free to create your first post!

Setting Up Authors on Your Blog