I totally agree with your points, but this approach has one big advantage - it's dead simple - define attributes and mapping and you're good to go.
But you can just give an upgrade path! consider something like this:
class Address
attr_accessor :street, :city
end
class Person
attr_accessor :address
end
class AddressMapper < Shale::Mapper
mapped_class Address
attribute :street, Shale::Type::String
attribute :city, Shale::Type::String
end
class PersonMapper < Shale::Mapper
mapped_class Person
attribute :address, AddressMapper
end
# use like this
PersonMapper.from_xml("...."); PersonMapper.to_xml(person)
and then, for _dead_ simplicity, you can add another method
generate_mapped_class "Person"which will define that PORO class for user for extra DRYness. API is basically the same, no repetition, but amount of rewrite with new requirements is drastically less.
I'm not asking you to rewrite your library, and I probably won't write and release mine, just saying that considering future self isn't that hard. And yeah, it's a bit of a rant about ActiveRecord from user of Rails, since 2006.
def from_xml(xml_string)
new.tap { |o|
parse_xml(xml_string) do |key, value|
o.__send__(:"#{key}=", value)
end
}
end
It would then be possible to change this to: def from_xml(xml_string)
(mapped_class || self).new.tap { |o|
parse_xml(xml_string) do |key, value|
o.__send__(:"#{key}=", value)
end
}
end
This would make it easier to solve a larger problem of needing to serialize the same business object in different ways for different consumers with different levels of detail. It would also permit the construction of mappers for temporary objects that contain the details for more complex serializations that have indirect connections.To the point of rewriting: A halfway point is to drop inheritance in favour of include/extend'ing the models. If that's done cautiously, it allows for co-existing with model objects from libraries that require inheritance. That is, this:
class Person
include Shale::Mapper
end
is preferable to class Person < Shale::Mapper
end