Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何重构已弃用别名\u方法\u链的代码_Ruby On Rails_Ruby_Deprecated - Fatal编程技术网

Ruby on rails 如何重构已弃用别名\u方法\u链的代码

Ruby on rails 如何重构已弃用别名\u方法\u链的代码,ruby-on-rails,ruby,deprecated,Ruby On Rails,Ruby,Deprecated,我正在升级我的rails应用程序,我收到一条警告说,alias\u method\u chain不推荐使用。请改用模块#prepend。但我真的不明白如何处理这件事。如何更改下面的代码 def read_attribute_with_mapping(attr_name) read_attribute_without_mapping(ADDRESS_MAPPING[attr_name] || attr_name) end alias_method_chain :read_att

我正在升级我的rails应用程序,我收到一条警告说,
alias\u method\u chain不推荐使用。请改用模块#prepend
。但我真的不明白如何处理这件事。如何更改下面的代码

  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
基本上类似于导入一个模块,但它最终位于其他代码的“前面”(因此模块可以调用
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\u属性
,但它也可以是从超类继承的方法(例如
ActiveRecord::Base

这是一个更短但更神秘的版本,使用匿名模块:

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

如果这只在一个地方使用,我可以将其添加到该类中而不是作为模块吗?不,
prepend
需要一个模块,但它可以是匿名的内联模块,如上面的第二个示例所示。我添加了第三个示例,只是为了取笑如何隐藏该模块,但您很可能不想这样做。在我看来,它节省了很少的打字时间,几乎没有什么胜利。在没有模块的情况下可以实现这一点,就像
alias\u method\u chain
所做的那样,但通常坚持Rails的方式更令人愉快,除非你有充分的理由不这样做。