Thursday, June 14, 2012

First Fire Revised

It didn't take too long for me to find a better way to solve the issue from last week. I guess that's just the way these things happen...
If you haven't read last week's post, I'll summarize. I was looking for a way to validate a password and it's confirmation, without using a whole other column for the password confirmation field. M solution was to validate manually before updating, and then using the `except' command on the params hash to get just the parameters I want to save.
Turns out there's another option I did not think about, because I wasn't too familiar with the subject. This option involves using the `attr_accessor' method. This method, used in the model, creates a setter and getter for a virtual attribute for the model, which instead of being saved in the database, is only created as an instance variable. This method is mostly used in order to simplify complex forms, and it will also be very helpful in this scenario. Let's see how.

So here is my form again, just as it was in the previous post:
<%= simple_form_for(@user, ...) %>
...
<%= f.input :password %>
<%= f.input :password_confirmation %>
...
<% end %>

And here is my updated model:

#user.rb
...
attr_accessible :password_confirmation ...
attr_accessor :password_confirmation

validates :password, presence: true, confirmation: true
validates :password_confirmation, presence: true

And that's all there is too it. In fact, if you were to include the password_confirmation as a column in the database, everything would look the same except for that attr_accessor line.
It may be worth to mention that also in the form view the virtual attribute is treated as if it existed in the table, so no special code to add there either, while in the controller there is no need in manual validations or in manipulating the params hash like I did last time.

I must say, I was quite amazed by how simple this solution is, especially since it allows you to keep on using the normal validation methods.

That's it for this week. Next week I promise to fixate on something different :)

No comments:

Post a Comment