In the existing codebase, the xpath for non-primitive elements is from the downcased classname of the non-primitive class. This works well, but there are several cases where some more flexibility would be good.
For instance, consider this XML:
```
1
22
4:40:15 PM
5:18:53 PM
6:06:17 PM
6:41:49 PM
```
There is an obvious problem with this xml: the q1, q2, q3, q4 elements should be ‘quarter’ elements, with an attribute containing the quarter number. However, we usually don’t have control of the format of external xml, so we just need to work with it. Anyway, we might map these with the following classes:
```
class Quarter
include HappyMapper
element :start, String
end
class Details
include HappyMapper
element :round, Integer
element :quarter, Integer
end
class Game
include HappyMapper
has_one :details, QuarterTest::Details
has_one :q1, QuarterTest::Quarter
has_one :q2, QuarterTest::Quarter
has_one :q3, QuarterTest::Quarter
has_one :q4, QuarterTest::Quarter
end
```
The problem is that the elements q1, q2, q3 and q4 will not be able to be found using the current HappyMapper implementation, since the xpath used will be ‘quarter’, which will find game/details/quarter in each case. Adding :tag => ‘q1’ etc will not help, since the tag name is derived from the class name.
We can fix this and allow mapping classes to be resuable. Instead of using the classname as the default tag name, we can use the following finders, in order:
1. specified tag (e.g. :tag => ‘q1’)
2. name of element (e.g. from has_one :q1)
3. tag_name (derived from class name by default)
Using this method, the Game class changes to:
```
class Game
include HappyMapper
has_one :details, QuarterTest::Details
has_one :q1, QuarterTest::Quarter, :tag => ‘q1’
has_one :q2, QuarterTest::Quarter, :tag => ‘q2’
has_one :q3, QuarterTest::Quarter, :tag => ‘q3’
has_one :q4, QuarterTest::Quarter, :tag => ‘q4’
end
```
This is a bit of a change, but the additional flexibility and reusability has worked really well for me in a variety of situations. In the existing specs, I only had to make one change for everything to pass:
```
class Radar
include HappyMapper
- OLD: has_many :places, Place
- NEW:
has_many :places, Place, :tag => :place
end
```
I’ve made the changes needed in my fork (http://github.com/lightningdb/happymapper/tree/master, commits ce59623df1ce0b16bbbee89e6fac2b2473756a43 and 3251509d1e68fb652227a42b1e5593ee8bc19d5b), and updated the gemspec version to 0.3.0 to reflect that the change might need minor changes to existing mappings. I think the flexibility is worth it though.
Any thoughts or questions?