使用 "update" 方法后,为 Rails 中的未定义属性调用 method_missing

Calling method_missing for undefined attributes in Rails after using "update" method

是否有 obj.update(attr1: "something") 方法调用 method_missing 而不是引发错误 ActiveModel::UnknownAttributeError (unknown attribute 'attr1' for Obj.) 的捷径?

我正在考虑简单地拯救它,然后 mimicking/calling method_missing,但这种方式感觉太笨重了。

是这样的吗?

  rescue_from ActiveModel::UnknownAttributeError do |exception|
    raise NoMethodError
    # or however you want to hanle
  end

你可以试试这个:

begin
  obj.update(attr1: "something")
rescue Exception => ex
  if  ex.class == ActiveRecord::UnknownAttributeError
    method_missing
  else
    raise ex
  end
end

source code (Rails 4.2) it seems that ActiveRecord::UnknownAttributeError is raised when the model instance does not respond_to? to the given attribute setter. So what you have to do is define a method_missing as well as respond_to_missing? in the model for all your dynamic attributes. This is actually what you always should do 无论如何使用 method_missing 时:

class Model < ActiveRecord::Base

  DYNAMIC_ATTRIBUTES = [:attr1, :attr2]

  def method_missing(method_name, *arguments, &block)
    if DYNAMIC_ATTRIBUTES.map { |attr| "#{attr}=" }.include?(method_name.to_s)
      puts "custom code for #{method_name} #{arguments.first.inspect}"
    else
      super
    end
  end

  def respond_to_missing?(method_name, include_private = false)
    DYNAMIC_ATTRIBUTES.map { |attr| "#{attr}=" }.include?(method_name.to_s) || super
  end

end

在 Rails 控制台中测试

Model.first.update(attr1: 'aa', attr2: 'bb')
# => custom code for attr1= "aa"
# => custom code for attr2= "bb"

Model.first.update(attr1: 'aa', attr2: 'bb', attr3: 'cc')
# => ActiveRecord::UnknownAttributeError: unknown attribute 'attr3' for Model.