简体   繁体   中英

How to refactor code for deprecated alias_method_chain

I'm upgrading my rails application and I'm getting a warning saying alias_method_chain is deprecated. Please, use Module#prepend instead alias_method_chain is deprecated. Please, use Module#prepend instead . But I'm not really understanding how to handle this. How can I change the code below?

  def read_attribute_with_mapping(attr_name)
    read_attribute_without_mapping(ADDRESS_MAPPING[attr_name] || attr_name)
  end
  alias_method_chain :read_attribute, :mapping

prepend is basically like importing a module, but it ends up "in front" of other code (so the module can call super to run the code it's in front of).

This is a runnable example with something close to your situation.

module MyModule
  def read_attribute(attr_name)
    super("modified_#{attr_name}")
  end
end

class Example
  prepend MyModule

  def read_attribute(attr_name)
    puts "Reading #{attr_name}"
  end
end

Example.new.read_attribute(:foo)
# Outputs: Reading modified_foo

I defined read_attribute directly on Example , but it could just as well have been a method inherited from a superclass (such as ActiveRecord::Base ).

This is a shorter but more cryptic version that uses an anonymous module:

class Example
  prepend(Module.new do
    def read_attribute(attr_name)
      super("modified_#{attr_name}")
    end
  end)

  def read_attribute(attr_name)
    puts "Reading #{attr_name}"
  end
end

Example.new.read_attribute(:foo)
# Outputs: Reading modified_foo

UPDATE:

Just for fun and to address a question below, here's how it could be done without having to explicitly make any modules yourself. I don't think I'd choose to do it this way myself, since it obscures a common pattern.

# You'd do this once somewhere, e.g. config/initializers/prepend_block.rb in a Rails app.
class Module
  def prepend_block(&block)
    prepend Module.new.tap { |m| m.module_eval(&block) }
  end
end

# Now you can do:
class Example
  prepend_block do
    def read_attribute(attr_name)
      super("modified_#{attr_name}")
    end
  end

  def read_attribute(attr_name)
    puts "Reading #{attr_name}"
  end
end

Example.new.read_attribute(:foo)
# Outputs: Reading modified_foo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM