Confusion with super-Collection of common programming errors

tl;dr: super behaves in unexpected ways, and variables matter, not just objects.

When super is called, it’s not called with the object that was passed in.

It’s called with the variable that is called options at the time of the call. For example, with the following code:

class Parent
  def to_xml(options)
    puts "#{self.class.inspect} Options: #{options.inspect}"
  end
end

class OriginalChild < Parent
  def to_xml(options)
    options.merge!(:methods  => [ :murm_case_name, :murm_type_name ])
    super
  end
end

class SecondChild < Parent
  def to_xml(options)
    options = 42
    super
  end
end

begin
  parent_options, original_child_options, second_child_options = [{}, {}, {}]
  Parent.new.to_xml(parent_options)
  puts "Parent options after method called: #{parent_options.inspect}"
  puts
  OriginalChild.new.to_xml(original_child_options)
  puts "Original child options after method called: #{original_child_options.inspect}"
  puts
  second_child_options = {}
  SecondChild.new.to_xml(second_child_options)
  puts "Second child options after method called: #{second_child_options.inspect}"
  puts
end

Which produces the output

Parent Options: {}
Parent options after method called: {}

OriginalChild Options: {:methods=>[:murm_case_name, :murm_type_name]}
Original child options after method called: {:methods=>[:murm_case_name, :murm_type_name]}

SecondChild Options: 42
Second child options after method called: {}

You can see that with SecondChild the super method is called with the variable options which refers to a Fixnum of value 42, not with the object that was originally referred to by options.

With using options.merge!, you’d modify the hash object that was passed to you, which means that the object referred to by the variable original_child_options is now modified, as can be seen in the Original child options after method called: {:methods=>[:murm_case_name, :murm_type_name]} line.

(Note: I changed options to 42 in SecondChild, rather than call Hash#merge, because I wanted to show it wasn’t merely a case of side effects on an object)