ActiveType::Object: Be careful when overriding the initialize method

Background:

ActiveType::Object inherits from ActiveRecod::Base and is designed to behave like an ActiveRecord Object, just without the database persistence.

Don't remove any of the default behavior of the initialize method!

If you have a class which inherits from ActiveType::Object and you need to override the #initialize method, then you should be really careful:

  • Always pass exactly one attribute. ActiveRecod::Base objects really want to get their arguments processable as keyword arguments. Don't change the syntax, or you'll experience pain.
  • Always call super inside of your overridden #initialize method. A lot of magic things happen in the ActiveRecord world. Just let them happen, otherwise kittens will die somewhere. You don't want that.

Example

class Item < ActiveType::Object

  def initialize(attributes)
    super
  
    # Now, as the ActiveRecod::Base part could do it's duty, I can freely do whatever I want.
  end

end

Example pitfall

  • If you don't run the super method inside #initialize, the object is marked as frozen. Rspec mocks (e.g. using partial doubles Show archive.org snapshot with receive(partial_double).to ...) in tests would raise the following error (just imagine how hard debugging can be):
ArgumentError:
       Cannot proxy frozen objects, rspec-mocks relies on proxies for method stubbing and expectations.
  • If you define initialize with no argument and don't call super, initialize might be hit with this error:
ArgumentError: 
       Wrong number of arguments (given 1, expected 0)

Further readings

Jakob Scholz Over 1 year ago