Topic: sanitize ajax response

On the signup form for my website, I'm adding an ajax button to check if a username is available. The method in the controller looks like this:

def check_username
  username = params[:username]
  if username !~ /^\w{4,20}$/
    render :text => '"' + username + '" is not a valid username'
  else
    user = User.find_by_username(username)
    if user.nil?
      render :text => '"' + username + '" is available'
    else
      render :text => '"' + username + '" is not available'
    end
  end
end

How do you sanitize the username in the render calls? The sanitize method is not available from the controller.

Re: sanitize ajax response

CGI::escapeHTML(username)

You may want to make a check_username.rhtml view file though.

Railscasts - Free Ruby on Rails Screencasts

Re: sanitize ajax response

So to use a view instead, I would just replace those render calls with an instance variable that the rhtml file uses, and then use the h method in the view to sanitize that variable?

Re: sanitize ajax response

Hmm, I was initially thinking of moving most of that method into the view, but that would place too much logic in the view. Actually, validation should be handled by the model anyway. So what I would do is this:

# in user.rb
validates_uniqueness_of :username

# in controller
def check_username
  @user = User.new(:username => params[:username])
  @user.valid? # runs the validations
  render :text => CGI::escapeHTML(@user.errors.on(:username).to_sentence)
end


Untested. You will probably need to adjust it a bit.

I'm still not completely satisfied with the solution. There was an article a while ago on handling model validation with AJAX. Can't find it now though.

Last edited by ryanb (2006-11-21 14:49:21)

Railscasts - Free Ruby on Rails Screencasts

Re: sanitize ajax response

Interesting stuff. I was wondering how to not repeat the regexp username validation that I had in the model.

If I understand this correctly, the valid? method runs ALL the validations on the model, but you only check for the errors you're interested in by using the @user.errors.on() method? So if @user.errors.on(:username) is nil, the username is available, otherwise the error is either that the username already exists, or it's not a valid username.

I'm pretty new to both ruby and rails so I'd never have come up with something like this. Thanks.

By the way, the to_sentence method always errors out on me with:

undefined method `to_sentence' for #<String:0x68fbba4>

Re: sanitize ajax response

The errors.on method is annoyingly strange. I would prefer it to always return an array, but it either returns nil, a string, or an array depending upon how many errors there are. Try this instead:

@user.errors.on(:username).to_a.to_sentence

Railscasts - Free Ruby on Rails Screencasts