Overriding attributes

17 views
Skip to first unread message

Nicholas Wieland

unread,
Aug 13, 2014, 9:52:29 AM8/13/14
to ohm-...@googlegroups.com
Hi *, I'm experiencing a very weird problem that I'm not able to track and solve.
This is my code:

  class User < Ohm::Model
    attribute :username
    attribute :password

    index :username

    def password= string
      @attributes[:password] = BCrypt::Password.create(string) # Tried self.password = BCrypt::whatever too
    end
  end

[15] pry(main)> User.find(username: 'test').first.password
=> "$2a$10$j1.s4hmuyCm8RffaEvB8IejaYOiZXWXId1Ccf8S0K3uXduxmMzyUq"
[16] pry(main)> User.find(username: 'test').first.password
=> "$2a$10$/0UzWtVsF.xczf4.UUqrP.PqYHxKs8fkIWKHlVVQVUNPFubzmuCwO"
[17] pry(main)> User.find(username: 'test').first.password
=> "$2a$10$ajlc3BYMOFXYDmy1a112ieXhMm39KoR1wPdPMp4WwEnxb2E35ypvC"
[18] pry(main)> User.find(username: 'test').first.password
=> "$2a$10$TlW87Gpd4RKpPutWzkePqeQiGri2ah.txDda4o6Lki7Sk1vayY9Fm"

Basically I'm able to set the password and encrypt it using BCrypt, but for some reasons every time I call the attribute the password is different.
I have no idea what's happening here, can someone help me?

TIA,
  ngw

Michel Martens

unread,
Aug 13, 2014, 10:48:38 AM8/13/14
to ohm-...@googlegroups.com
Hello Nicholas,

When Ohm loads the attributes from the database, it doesn't assign it
to @attributes directly. Instead, it uses the accessor to allow for
any kinds of type casting. In your case, what's happening is that each
time Ohm loads the password field from Redis, it processes it again
with BCrypt. To see the code in question, check here:

https://github.com/soveran/ohm/blob/50f0dd780af5db7e8a88253212db5761af025cc5/lib/ohm.rb#L1468-L1471

What we usually do is a bit different: we define an attribute
`crypted_password` in Ohm, and then in the model we define a method
`password=` that takes a string and produces the crypted version,
which is then stored in the `crypted_password` attribute. We use a gem
called Shield, here's the relevant code:

https://github.com/cyx/shield/blob/a67dd135cb5c267ddfc95753b49883ee21aad5b5/lib/shield.rb#L95-L97

You can do something similar to what we do with Shield and use BCrypt
instead. You have to define an attribute `crypted_password`, then a
method called `password=` that is a bit different from what you
currently have:

class User < Ohm::Model
attribute :username
attribute :crypted_password

index :username

def password= string
self.crypted_password = BCrypt::Password.create(string)
end
end

That should work, and you will have to use `crypted_password` for
authenticating users.
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "Ohm Ruby" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to ohm-ruby+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages