Skip to content
This repository

Allowing reusable mapping classes #3

Open
jnunemaker opened this Issue April 16, 2009 · 0 comments

1 participant

John Nunemaker
John Nunemaker
Owner

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:

1224:40:15 PM5:18:53 PM6:06:17 PM6: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
  1. OLD: has_many :places, Place
  2. 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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.