Not able to save Single Table inheritance
obromios opened this issue · 4 comments
I have a User model, where I have declared
attr_encrypted :email, key: [ENV["EMAIL_ENCRYPTION_KEY"]].pack("H*")
blind_index :email, key: [ENV["EMAIL_BLIND_INDEX_KEY"]].pack("H*")
It has fields for email and type. If I retrieve a user where type is nil i.e. u=User.where(type: nil).first
then
u.email ='plain@user.com'
u.save
works by filling out the encrypted fields and User.where(email: 'plain@user.com') works as expected.
However I also have a DormantUser type
class DormantUser < User
def dormant?
true
end
end
If retrieve a DormantUser e.g. dormant = DormantUser.first
and then do
dormant.email = 'dormant@user.com'
dormant.save
gives the following errror
ArgumentError: wrong number of arguments (given 2, expected 1)
/gems/blind_index-0.3.0/lib/blind_index.rb:21:in `generate_bidx'
How should I use the blind_index gem with Single Table Inheritance?
I tried out master and it does indeed work. It is a neat gem, thank you. One thing to consider is that when I first tried it for the DormantUser, I received the error:
TypeError: no implicit conversion of nil into Hash
gems/blind_index-d431befe9886/lib/blind_index/model.rb:24:in `merge'
Upon inspection of your test code, I tried putting the following in dormant_user.rb
blind_index :child, key: [ENV["EMAIL_BLIND_INDEX_KEY"]].pack("H*")
which worked fine. Is that the correct way to do this? Maybe it was just me, but if this is not obvious, it might be worth noting in your readme file.
I was adding this to an existing application and quite a few of my tests failed. The reasons for failure were pretty obvious, but I just document them below in case other people come across the same problems:
- update_columns does not work to save the email address, whilst update does work. Presumably because your gem does something at validation.
- SQL searches that use LIKE do not work anymore. I suspect there are a number of other SQL terms that do not work.
- find_by_email does not work, presumably because there is no longer an email column. Because I used this a lot, I added the following code to the User model
def self.find_by_email(email)
where(email: email).first
end
Incidently I first tried
scope :find_by_email, ->(email) { where(email: email).first }
but this did not work on the empty case where it returned [] rather than nil. But maybe I just wrote the scope incorrectly?
Hey @obromios, thanks for the detailed update. I fixed the TypeError
and added support for dynamic finders on master. You're correct about update_columns
as it's designed to bypass callbacks. Also, only the equality operation will work when the data is hashed. Lastly, as far as I know, you can't return single records from scopes, which is why it returns an empty array instead of nil.