Writing an Ajax-based Password-Generator with Ruby on Rails

Categories: Tutorials, Web-Development

As I am learning Ruby on Rails, I wanted to share some knowledge about it. So here it is: A tutorial of how to write a password-generator with Ruby on Rails. You can see the result here (hosted on heroku).

Requirements

I don't explain how to install Ruby on Rails. So please install it first following this tutorial.

$ ruby --version
ruby 1.9.3p194 (2012-04-20)
$ rails --version
Rails 3.2.8

Creating a Ruby on Rails-Project

First we have to create a new Rails-Project. You can use any command line to do that. I use Aptana Studio, as it provides a console next to the code editor. So to create a new project type:


$ rails new passwordgenerator

This will create a folder passwordgenerator. Inside that folder you see many other folders like app and public. If you have ever worked with another web-framework like Zend for PHP you will know what those mean. If not heres a short explanation: The folder app contains all controllers, models and views of your application. Its the folder you will need most in this tutorial. The folder public is the folder that will be accessed by the users. The other folders are not that important for now as this is a very simple application.

To test your application navigate into the folder passwordgenerator and run the Testserver WEBrick:


$ cd passwordgenerator
$ rails server

Open your browser and go to http://localhost:3000 and you will the a "Welcome"-Page. It works! 🙂

Generating a Controller

Ruby on Rails uses the model-view-controller design pattern.  A controller has so called actions. Those actions are usual methods, but with each request the routing will determine which action to run. For example: localhost:3000/foo/bar will run the bar-method of controller foo.

For our application we need a controller with two actions. One action will show a form, where different options can be set. The other action will generate passwords. So we create a controller password with the action index and generate. Go to command line and run the following command:


rails generate controller password index generate

This generates a controller app/controllers/passwort_controller.rb and two views app/views/password/index.html.erb and app/views/password/generate.html.erb.

The View

First we want to create a form providing the user some options like password-length. As this form should be the first thing the user sees, we need to route our home to the index-action of our password-controller. Go to config/routes.rb and add the following line (between do and end):


root :to =>"password#index"

Then remove the index.html from your public folder and start WEBrick again. You will now find the index-action of the password-controller under http://localhost:3000.

The view we need to edit is app/views/password/index.html.erb. Open it with your editor of choice and remove its content. We now create a form with the Rails FormTagHelper:

<%= form_tag({:controller => "password", :action => "generate"}, {:method => "get", :remote => true, :id="optionsform"}) do %>
<% end %>

This generates a <form>-Element which leads to the password-controllers generate-action. The forms method is set to "GET" and the custom HTML5 data-remote-attribute is set to "TRUE". The data-remote-attribute tells Rails to submit it via AJAX.

As the form is empty for now, lets add some form-elements. Here is an example how to do that, but you also could use checkboxes or radio-buttons (have a look at the API to find out what else is possible):

<%= form_tag({:controller => "password", :action => "generate"}, {:method => "get", :remote => true, :id="optionsform"}) do %>

 <%= label_tag("pw_length", "Password-Length:") %>
 <%= text_field_tag("pw_length") %>
 <br />

 <%= label_tag("pw_count", "How many passwords do you need?") %>
 <%= text_field_tag("pw_count") %>
 <br />
 <br />

 <%= label_tag("upper", "Use Upper-Case [ABCDE...]") %>
 <%= select_tag("upper", options_for_select([["Yes", "1"], ["No", "0"]])) %>
 <br />

 <%= label_tag("numbers", "Use Numbers [1234...]") %>
 <%= select_tag("numbers", options_for_select([["Yes", "1"], ["No", "0"]])) %>
 <br />

 <%= label_tag("lower", "Use Lower-Case [abcde...]") %>
 <%= select_tag("lower", options_for_select([["Yes", "1"], ["No", "0"]])) %>
 <br />
 <br />

 <%= submit_tag("Generate") %>

<% end %>
<div id="passwordlist"></div>

The div-Container called "passwordlist" will show the generated passwords. Thats all for now. If you visit your website now, you find a form with some options and a "Generate"-Button:

The Controller

In the PasswordController we want the generate-method to answer the XHR-Request which is sent by the form we created earlier. So first we check the parameters sent in the XHR-Request. The most important parameters to check are the password-length and -count, because we need them to be converted to Integers:


begin
  @pw_length = Integer(params["pw_length"])
rescue
  @response << "Please enter a valid Password-Length<br/>"
end

begin
  @pw_count = Integer(params["pw_count"])
rescue
  @response << "Please enter a valid Password-Count<br/>"
end

After this simple check, we look at the other parameters, which define the chars we use in the password. After building a string containing all possible chars, we can start to generate passwords. Within two for-loops we pick chars from the possible-chars-string randomly until the password-length and password-count is reached. Those passwords are appended to a response-string (with html-tags). This response-string is sent to the view:

if @response.empty?
  @possible=""
  if params["upper"] == "1"
      @possible << "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  end
  if params["lower"] == "1"
      @possible << "abcdefghijklmnopqrstuvwxyz"
  end
  if params["numbers"] == "1"
      @possible << "1234567890"
  end

  #Generate Passwords
  if not @possible.empty?
      @response="<ul>"
      for i in 1..@pw_count
          pw=""
          for j in 0..@pw_length
              pw << @possible[rand(@possible.length)]
          end
          @response << "<li>#{pw}</li>"
      end
      @response << "</ul>"
  else
      @response="Error: Cannot build passwords without chars."
  end
end

render :text => @response, :content_type => 'text/html'

If you press the generate button now, you will receive the response-string as answer (you can see that using a tool like FireBug).

The JavaScript

To show the generated passwords, we need some JavaScript. Go to /app/assets/javascript/ and open application.js. Add the following lines to it:


jQuery(function($) {
    $('#optionsform').bind('ajax:before', function(evt, data, status, xhr) {
        $("#passwordlist").html("loading....");
    });
    $('#optionsform').bind('ajax:success', function(evt, data, status, xhr) {
        $("#passwordlist").html(data);
    });
});

We bind the optionsform ajax-events to simple JavaScript-functions. The function bound to ajax:before shows a "loading..." as long it takes to get an answer from the controller. The function bound to ajax:success shows the generated response-string.
Thats it. You can go to your website and generate passwords as you like. For additional training try to add more options (take a look at the Ruby on Rails-APIs) or a better password-generating algorithm to it. You can see the result here (hosted on heroku) or download the source-code:

As I am also new to Ruby on Rails, feel free to comment if I made mistakes or if you think there is a better/easier way of doing this.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>