Tuesday, June 5, 2012

First Fire

Hi there.
This blog is here mainly in order to share the stuff I learn about RoR while on the job, for others to learn and contribute, for future reference, and for fun.
I am currently working on a pretty big project - creating an alumni web-portal for a relatively large non-profit organization. When I say relatively, I mean for me, and when I say large I mean about 3000 existing graduates, and about 300 more every year or so. I started a month ago, and the launching deadline is in about another month. Thing is, I'm a year-old noob as far as Ruby on Rails, and this is by far the most complex challenge I have ever been faced with in my career. Oh, and the god damn web-designers haven't come through with the final designs yet, so we're a bit off schedule.

I want to share a little neat trick I learned today, which, as far as I'm concerned is a solution to a fairly annoying problem. The thing is, I'm not quite sure it's the best solution out there, so if anyone knows of a better way to do this, let me know!
So let's dig in:

In the sign-up form, the user is asked to enter his password twice, once in the password field, and another in the confirmation field. In the from, the most simple way to do this would be this:

<%= simple_form_for(@user, ...) %>
...
<%= f.input :password %>
<%= f.input :password_confirmation %>
...
<% end %>

(* In my code I use many methods from gems such as simple_form and bootstrap that might be unfamiliar to some, but the methods are pretty straightforward, and besides, you should probably check these gems out!)

The problem with this is that in your standard create or update action, rails will try to pass this password_confirmation attribute to the model, and hit an error.

My initial solution to this was to create a column in the users table called password_confirmation, add the attribute to the attr_accessible method in the model, and then just live with an unnecessary column until the end of  time. That just won't do.

My second solution was quite silly, but it involved creating a dummy model, which would be used only to validate the password confirmation, and thus would never actually be saved. However this was like taking a walkman to a party after you've decided not to take a diskman. An unused model is far worse than an unused column.

My third solution was to somehow omit the password_confirmation from the parameters sent to the model, however this would mean implementing my own confirmation validation before saving. At this point I ran out of ideas, and the internet was giving me too many deprecated solutions. So I went for it, and this is how I did it:

def create
@user.confirm_password
@user= User.new(params[:user].except(:password_confirmation))
...
end
...
def update
@user.confirm_password
if @user.update_attributes(params[:user].except(:password_confirmation))
...
end

I think it's pretty staight forward, but in short, the except method allows you to omit certain entries from the params hash with ease. The confirm_password method is used to do exactly what the confirmation validation does, so it's not ideal, but I prefer that to having unnecessary columns or models...

No comments:

Post a Comment