Is there a clean API for resetting instance variables on 'reload' in ActiveRecord?

前端 未结 3 694
陌清茗
陌清茗 2021-01-07 22:23

In an ActiveRecord::Base model, I can reset the state of the model to what it was when I got it from the database with reload, as long as the attri

相关标签:
3条回答
  • 2021-01-07 23:07

    ActiveRecord does not provide a way to do this, it can only acts on the model attributes.

    That being said, I think a more elegant way to do it would be to loop over the ivars and set them to whatever you like :

    class User < ActiveRecord::Base
      def reload(options = nil)
        super
        self.instance_variables.each do |ivar|
          next if ivar == '@attributes'
          self.instance_variable_set(ivar, nil)      
        end
      end
     end
    

    Note that we skip @attributes because AR is taking care of it when you reload the attributes.

    0 讨论(0)
  • 2021-01-07 23:08

    Rework Jean-Do's answer slightly. It doesn't break default instance_variables and relations.

    after_initialize do 
      @default_instance_variables = instance_variables
    end
    
    def reload(options = nil)
      super
      self.instance_variables.each do |ivar|
        if ivar == :'@default_instance_variables' || 
          @default_instance_variables.include?(ivar)
          next 
        end
        remove_instance_variable(ivar)
      end
      self
    end
    
    0 讨论(0)
  • 2021-01-07 23:09

    I took gayavat's answer and reworked it into my test_helper.rb file, because I didn't want to override the usual #reload method.

    class ActiveRecord::Base
      attr_accessor :default_instance_variables
      after_initialize do 
        @default_instance_variables = instance_variables
      end
    end
    def reload_ivars(obj)
      obj.reload
      obj.instance_variables.each do |ivar|
        if ivar == :'@default_instance_variables' || 
         obj.default_instance_variables.include?(ivar)
          next 
        end
        obj.send(:remove_instance_variable, ivar)
      end
    end
    

    When I need to reload something in a test I just call reload_ivars(object).

    0 讨论(0)
提交回复
热议问题