jgaskins / perpetuity

Persistence gem for Ruby objects using the Data Mapper pattern
http://jgaskins.org/blog/2012/04/20/data-mapper-vs-active-record/
MIT License
250 stars 14 forks source link

Creating objects in memory uses `Object.allocate` #5

Closed jgaskins closed 12 years ago

jgaskins commented 12 years ago

Currently, objects are not instantiated with .new because constructors may require parameters, which would raise an exception. Using allocate isn't necessarily a bad thing, but it could cause a lot of trouble (and confusion) if a class' constructor initializes variables that aren't initialized anywhere else.

class Widget
  def initialize
    @subwidgets = []
  end
end

@subwidgets will not be initialized. If it's one of the attributes that gets persisted, this isn't a problem, but if it isn't it will be nil after being retrieved from the DB when the object expects it to be an Array.

jgaskins commented 12 years ago

Been thinking about this and I think we could either enforce a rule that mapped classes respond to a naked .new call or we could provide some interface to specify arguments when loading from the DB so that we can instantiate with .new(*args). Something like this:

class Article
  attr_accessor :title, :body
  def initialize(title, body)
    @title, @body = title, body
  end
end

Perpetuity::Mapper.generate_for Article do
  attribute :title, String
  attribute :body, String

  default_args('', '') # When loading from the DB, this calls Article.new('', '')
end

However, I don't see how that is at all better than having default args inside the mapped class' initialize method: def initialize(title='', args='').