.

How to use an auto_complete to validate passwords

As a follow up to my previous article about using auto_completes to ensure unique filenames, I’ve put together a bit of code that does essentially the same thing except that it checks a password field to ensure that it meets certain criteria.

  1. # view file
  2. <%= text_field_with_auto_complete :user, :password %><div id=login_error></div>
  3.  
  4. # model file
  5.  
  6. def User < ActiveRecord::Base
  7.   validates_length_of :password, :in=>3..20
  8. end
  9.  
  10. # controller file
  11.  
  12. def auto_complete_for_user_password
  13.   @user = User.new(params[:user])
  14.   @user.valid# ensures the errors array is populated
  15.   password_errors = @user.errors.on(‘password’)
  16.   render :update do |page|
  17.      page.replace_html ‘login_error’, (password_errors.empty? ? "" : password_errors)
  18.    end
  19. end

This will indicate when a password does not meet the validation criteria defined in the model. You can add custom validations to check the strength of the password itself.

Passing extra data with an auto_complete

I recently found myself trying to use an auto_complete field to allow the user to select an object from a list of possible objects. That’s all fine and dandy, but I wanted to exclude certain values depending on which object I was editing. There are at least two ways to do this, the first is to stuff the extra data into the session and then read that value from the auto_complete_for method and act appropriately.

I don’t really like this approach because I don’t want to clutter up the session with various form parameters. Thankfully, there is a simple way to do this by once again abusing the built in text_field_with_auto_complete function…

  1. # View
  2. <%= text_field_with_auto_complete ‘new_object’, ‘name’, { :tabindex=>1 }, {:url=>{:action=>’auto_complete_for_object_name’, :extra=>@object.extra} %>

[In my case, I used the :extra data to exclude certain objects from the auto_complete_for response]

By passing the :url option, you rewrite the URL that the AJAX actions call, enabling you to add extra parameters that can be acted on by the method. Also note that you can change the name of the action called (in fact, you need to specify it or it will default to the name of the action for the current view… probably not what you want). This is handy because it lets you assign the response to a variable with a different name without writing a separate auto_complete_for handler. In this case, the submitted form will have a ‘new_object[name]‘ in the params, even though the action called was ‘auto_complete_for_object_name’.

Needless to say, you need to write a custom ‘auto_complete_for’ method to handle the extra data. Note that you could also use this method to handle multiple auto_complete fields.

Using an auto_complete to ensure uniqueness

The Problem

Occasionally there is a need to have a user enter a unique string. For example, if you want to ensure that a new user’s login id is not used by someone else. The traditional rails way of doing this is to set up a ‘validates_uniqueness_of’ validation on the model and then catch the error when you try to save the record.

From the user’s point of view, this can be a horrendously painful experience that can be akin to trying to outsmart the Sphinx.

Form: “please enter a unique login id’
User: “john smith”
Form: “Wrong, guess again!”
User: “jsmith”
Form: “Nope, getting warmer”
User: “jsmith1″
Form: “You wish! Keep trying!”
User: “as;ldfkjasd;flkajsdf;lakjsd”
Form: “Ha! your id must be only numbers and letters!”
User: “!@!$!@!#!@#!@#!@#%*(#^($!!!!!!!”
Form: “Sorry, wrong again!”
* user navigates to youtube *

The biggest problem here is that there is no feedback to the user if the value they selected is valid until they submit. Some forms will also force you to retype your new password everytime this fails as well. Double ouch!

Solutions

  1. offer suggestions for valid responses when it fails the first time. Not exactly the best, you might as well autogenerate their id for them and hope they don’t forget it.
  2. provide feedback with AJAX to let them know if the value is ok.

As you might have guessed from the title of the article, I’m going to show you how to do this with a standard rails auto_complete text field.

  1. # view file
  2. <%= text_field_with_auto_complete :user, :login_id %><div id=login_error></div>
  3.  
  4. # controller file
  5.  
  6. def auto_complete_for_user_user_name
  7.   @user = User.find_by_user_name(params[:user][:user_name])
  8.    render :update do |page|
  9.      page.replace_html ‘login_error’, (@user ? "Login id already in use" : "")
  10.    end
  11. end

That’s it. Anytime the auto_complete matches a record, it will change the ‘login_error’ div to indicate there’s a problem.

Net result…. a much better user interface experience and much happier users. (more…)

Next Page »