开发者

Ruby/RoR: calling original method via super()?

开发者 https://www.devze.com 2023-02-14 03:51 出处:网络
In a RoR app, I want to specialize ActiveRecord\'s update_attributes() method i开发者_JAVA百科n one of my models, extracting some of the attributes for special handling and passing the rest of them to

In a RoR app, I want to specialize ActiveRecord's update_attributes() method i开发者_JAVA百科n one of my models, extracting some of the attributes for special handling and passing the rest of them to the original update_attributes() method. The details:

class Premise < ActiveRecord::Base
  ...
  def update_attributes(attrs)
    attrs.each_pair do |key, val|
      unless has_attribute?(key)
        do_special_processing(key, val)
        attrs.delete(key)
      end
    end
    # use original update_attributes() to process non-special pairs
    super.update_attributes(attrs)
  end
  ...
end

The call to super.update_attributes(attr) raises an error:

undefined method `update_attributes' for true:TrueClass

... which makes me suspect I really don't understand the super keyword in Ruby. What am I missing? Specifically, how do I call the original update_attributes() method?


In Ruby super is a special case where parenthesis do matter...

Calling super without parameter (nor parenthesis) in a method of a subclass calls the same method in the super-class (or its ancestors if the superclass does not define it) with all the parameter passed to the subclass method. So, here, you could have written simply super.

Calling super() calls the superclass (or ancestors) method without any parameter (assuming this method accept no parameters...)

Calling super(...) with any combination of parameters calls the superclass method, passing it the paramaters


You want:

super(attrs)

That will call the original method, passing attrs as an argument to it.

As it is now, you're trying to call update_attributes on the "true" value returned by the original update_attributes.


This looks like a better use for alias_method_chain:

def update_attributes_with_special(attrs)
  attrs.each_pair do |key, val|
    unless has_attribute?(key)
      do_special_processing(key, val)
      attrs.delete(key)
    end
  end
  update_attributes_without_special(attrs)
end
alias_method_chain :update_attributes, :special
0

精彩评论

暂无评论...
验证码 换一张
取 消