Repository: rails/rails
File: activesupport/lib/active_support/current_attributes.rb (Ruby)

Code before:
        invalid_attribute_names = names.map(&:to_sym) & INVALID_ATTRIBUTE_NAMES
        if invalid_attribute_names.any?
          raise ArgumentError, "Restricted attribute names: #{invalid_attribute_names.join(", ")}"
        end

        ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
          names.each do |name|
            owner.define_cached_method(name, namespace: :current_attributes) do |batch|
              batch <<
                "def #{name}" <<
                "@attributes[:#{name}]" <<
                "end"
            end
            owner.define_cached_method("#{name}=", namespace: :current_attributes) do |batch|
              batch <<
                "def #{name}=(value)" <<
                "@attributes[:#{name}] = value" <<
                "end"
            end
          end
        end

        Delegation.generate(singleton_class, names, to: :instance, nilable: false, signature: "")
        Delegation.generate(singleton_class, names.map { |n| "#{n}=" }, to: :instance, nilable: false, signature: "value")

        current_instances.delete(current_instances_key)
        self.defaults = defaults.merge(names.index_with { default })
      end

      # Calls this callback before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
      def before_reset(*methods, &block)
        set_callback :reset, :before, *methods, &block
      end

      # Calls this callback after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
      def resets(*methods, &block)
        set_callback :reset, :after, *methods, &block
      end
      alias_method :after_reset, :resets

      delegate :set, :reset, to: :instance

      def reset_all # :nodoc:
        current_instances.each_value(&:reset)
      end

      def clear_all # :nodoc:
        reset_all
        current_instances.clear
      end


Review comment (suggestion):
I think it would be better if we avoided the call to `instance`, we can probably do it by not using `respond_to?` but `singleton_class.method_defined?`.



Code after:
        invalid_attribute_names = names.map(&:to_sym) & INVALID_ATTRIBUTE_NAMES
        if invalid_attribute_names.any?
          raise ArgumentError, "Restricted attribute names: #{invalid_attribute_names.join(", ")}"
        end

        ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
          names.each do |name|
            owner.define_cached_method(name, namespace: :current_attributes) do |batch|
              batch <<
                "def #{name}" <<
                "@attributes[:#{name}]" <<
                "end"
            end
            owner.define_cached_method("#{name}=", namespace: :current_attributes) do |batch|
              batch <<
                "def #{name}=(value)" <<
                "@attributes[:#{name}] = value" <<
                "end"
            end
          end
        end

        Delegation.generate(singleton_class, names, to: :instance, nilable: false, signature: "")
        Delegation.generate(singleton_class, names.map { |n| "#{n}=" }, to: :instance, nilable: false, signature: "value")

        self.defaults = defaults.merge(names.index_with { default })
      end

      # Calls this callback before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
      def before_reset(*methods, &block)
        set_callback :reset, :before, *methods, &block
      end

      # Calls this callback after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
      def resets(*methods, &block)
        set_callback :reset, :after, *methods, &block
      end
      alias_method :after_reset, :resets

      delegate :set, :reset, to: :instance

      def reset_all # :nodoc:
        current_instances.each_value(&:reset)
      end

      def clear_all # :nodoc:
        reset_all
        current_instances.clear
      end

      private