Как изменить код для устаревшего alias_method_chain - PullRequest
0 голосов
/ 02 апреля 2020

Я обновляю свое приложение rails и получаю предупреждение «1001 *». Но я не совсем понимаю, как справиться с этим. Как я могу изменить код ниже?

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

1 Ответ

1 голос
/ 02 апреля 2020

prepend в основном похоже на импорт модуля, но в конечном итоге он оказывается «перед» другим кодом (поэтому модуль может вызвать super для запуска кода, перед которым он находится).

Это Это работоспособный пример с чем-то близким к вашей ситуации.

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

Я определил read_attribute непосредственно на Example, но он также мог бы быть методом, унаследованным от суперкласса (например, ActiveRecord::Base).

Это более короткая, но более криптовая версия c, в которой используется анонимный модуль:

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

ОБНОВЛЕНИЕ:

Просто для удовольствия и по адресу вопрос ниже, вот как это можно сделать без необходимости явно создавать какие-либо модули самостоятельно. Я не думаю, что решил бы сделать это сам, так как это скрывает общий шаблон.

# 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
...