Hiding an attribute in an ActiveRecord model

后端 未结 4 1130
庸人自扰
庸人自扰 2021-01-21 19:06

I am somewhat new to Rails and working on designing a User model using ActiveRecord. In this model, I have a password attribute which is intended to keep a hash of the user\'s p

4条回答
  •  醉酒成梦
    2021-01-21 19:49

    Let me tell a short story on why I had to go through similar path as you. I once had to "unsubscribe" lots of my model's attributes/columns.

    The thing is that I wanted to reach the column values through read_attribute method. I was on a quest where these columns should be removed from DB some weeks later, so I wanted to make a graceful migration of the data in these "deprecated" columns first (and port them into new tables) but I still wanted to use the same old attribute accessor methods throughout the app, but they would use the new DB structure.

    So instead of simple overwriting method by method (reader and writter) I simple wrote method_missing to catch all the old columns (through a Regex) and redirect their actions into a new logic. But I could only accomplish this if I could "undefine" the old accessor ("dirty") methods, otherwise they would never reach method_missing method.

    So after a lot of struggling I got into the following solution (adapting to your case):

    class Account < ActiveRecord::Base
    
      # ...
    
      unless attribute_methods_generated?
        define_attribute_methods
        undef_method "password"
        undef_method "password="
      end
    
      # ...
    
    end
    

    I just needed to remove the reader and writter methods, but you can remove all the other "dirty" methods if you want.

    The attribute_methods_generated? class method returns true if the dirty methods were already generated. Then it forces to generate the dirty methods and only then it removes the desired methods. If you simple try to use undef_method method directly in the class scope it'll throw an exception telling you the methods you're trying to remove don't exist (yet). That's why you need to make it that way above.

提交回复
热议问题