Open ronaldtse opened 2 months ago
@ronaldtse In some cases we can use modules to share code:
module BibliographicItem
def self.included(base)
base.class_eval do
attribute :schema_version, Shale::Type::String
...
xml do
map_attribute "schema-version", to: :schema_version
...
end
end
end
end
class Bibitem < Shale::Mapper
include BibliographicItem
@xml_mapping.instance_eval do
root "bibitem"
...
end
end
class Bibdata < Shale::Mapper
include BibliographicItem
@xml_mapping.instance_eval do
root "bibdata"
...
end
end
This is a pain for me as well, and I have already been yelling at the clown set up of this software. Repeating all accessors every time we inherit a class defeats the entire point of using classes to define accessors to XML and YAML.
For @opoudjis it’s even more painful because he needs to override only one element in a tree of Mapper classes, and it forces him to inherit the entire tree of classes but only override one.
This is a pain for me as well, and I have already been yelling at the clown set up of this software. Repeating all accessors every time we inherit a class defeats the entire point of using classes to define accessors to XML and YAML.
But can you design a syntax that address this? We can then find a way to implement it.
The most obvious thing to do would be to treat the do block like a class method (even if it isn't one), and introduce super
.
So:
class Uml2013 < Shale::Mapper
attribute :a, Uml2013String
attribute :b, Uml2013Note
xml do
root 'uml'
map_attribute 'A', to: :a
map_attribute 'B', to: :b
end
end
class Uml2016 < Uml2013
attribute :b, Uml2016Note
attribute :c, Uml2013Note
xml do
super
map_attribute 'C', to: :c
end
end
The other thing to do would be to modularise mappings in the XML block into class methods, which could then be overridden:
class Uml2013 < Shale::Mapper
attribute :a, Uml2013String
attribute :b, Uml2013Note
xml do
root 'uml'
mapA
mapB
end
def mapA
map_attribute 'A', to: :a
end
def mapB
map_attribute 'B', to: :b
end
end
class Uml2016 < Uml2013
attribute :b, Uml2016Note
attribute :c, Uml2013Note
def mapB
map_attribute 'B', to: :b
map_attribute 'C', to: :c
end
end
Shale provides format specific blocks such as:
When a class inherits from it, the
xml
block mapping is completely wiped:It is very inconvenient to have to re-specify all format-specific mappings.
This situation is terrible for versioned namespaces because let's say there is UML version 2013 vs version 2016, the objects are slightly different, but the entire format block really needs to get rewritten.
Here's an example of the ideal situation:
The correct situation is to have format specific mappings retained unless overridden. There could also be a command that removes all mappings should that be necessary, such as
xml! do
.