Forum: Ruby on Rails How do I automatically modify a method when accessing it?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Phoenix R. (Guest)
on 2009-04-11 05:14
(Received via mailing list)
I'm in a weird situation where I'm storing encrypted information in a
database.  For example, a User.name field would be stored in its
encrypted format, so its not human-readable when accessing:

User.name
=> ")@Nw0asna;sd//20b3Q#A02nsoasd                            \n"

(This is just an example.  I'm not actually encrypting names and the
model isn't User ;-)  But you get the idea.)

What I'm trying to figure out is the right way to go about
automatically assigning the "name" method to decrypt the data itself
when it's being pulled out for display.

For example, I tried:

def name
self.name = decrypt_name
end

private
def decrypt_name
decryption_object.decrypt(self.name)
end

----
However, that has obvious problems - in my test, it seems to form an
infinite loop, bouncing back and forth between the "name" method and
the decrypt_name method (because one calls the other).

Is there any way other than writing specific get and set methods to do
this?  I'd even be happy with a retrieval happening within find:

User.find(:first)
 => #<User id: 1, name: "John D.">

Even though "name" stored inside the database is actually encrypted.

Any thoughts?  Thanks :)
Phoenix R. (Guest)
on 2009-04-11 05:26
(Received via mailing list)
Okay, I think I'm on the right track.

I just found out that ActiveRecord::Base has a section on overwriting
default accessors.  So my basic method is now:

def name
  decrypt(read_attribute(:name))
end

The only thing that concerns me is that I also have a
before_save :encrypt_data call as part of the class definition.  So
let's say I submit a form via post:

@user = User.new(params[:user])
@user.save

If I read this right, when I call User.new, or if I were to specify
User.find(:first, :conditions => {:name => "John D."}), it would
first try to decrypt data *that isn't encrypted in the first place*).

Am I way off track here or is this about right, and if so, is there
any way I can automate the abstraction that needs to take place, so
that User.name, when accessed, is decrypted only if it's in an
encrypted form?

Hope that makes sense :)
This topic is locked and can not be replied to.