Giter Club home page Giter Club logo

ptolemy's Introduction

Ptolemy

Are you tired of ugly data munging in Rails controllers or models, for instance. Well, Ptolemy is a flexible mapping tool for mapping hashes and xml. It allows you define mappings separate from your code, keeping your code clean and focused on its core responsibilities. The mappings themselves are then easy to understand and modify if and when your code changes.

Ptolemy is a reworking of the Babel-icious mapping gem. Ultimately, I felt a name change would do the gem some good since the name ‘Babel-icious’, a play on the Tower of Babel, was often confused with the term ‘Babe-alicious’. Also, the name Ptolemy seemed eminently more suitable for a mapping gem given the impact of the historical figure Ptolemy on the science of geography.

Author

To Do

Add a mapper for JSON.

Examples

Ptolemy mappings should ideally be written in their own file or files, separate from the code that actually requires mapping. Just include the mapping files at runtime. A mapping is configured by passing mapping ‘coordinates’ to a ‘config’ block on the Mapper class:

Ptolemy::Mapper.config(:foo) do |m|

 m.direction :from => :xml, :to => :hash

 m.map :from => "foo/bar", :to => "bar/foo"
 m.map :from => "foo/baz", :to => "bar/boo"
 m.map :from => "foo/cuk/coo", :to => "foo/bar/coo"
 m.map :from => "foo/cuk/doo", :to => "doo"

end

The ‘config’ method takes a symbol as its first argument which serves as an identification tag for that mapping. The second argument is a block where you indiate the details of your mapping, which should include a direction indicator and individual mapping ‘coordinates’, as well as a series of ‘to’ and ‘from’ mappings. The line

m.direction :from => :xml, :to => :hash

tells the mapper that the source of the mapping will be xml and the target will be a hash. And the mapping coordinates

m.map :from => "foo/bar", :to => "bar/foo"

tell the mapper to place the value of element located at “foo/bar” in position “bar/foo”. Here, the slashes indicate nestings for both hashes and xml. So, given the hash:

{"foo" => {"bar" => "baz"}}

the slash indicates that “bar” is a nested hash within “foo”. The target xml then should be mapped as

<bar><foo>baz</foo></bar>

with the value of “bar” from the hash above placed in the nested <foo> tags in the xml.

Translation

When you want to translate the mappings, simply call:

Ptolemy::Mapper.translate(:foo, source)

passing the tag for the mapping and the actual source you want to translate from. The above line would translate the :foo mapping above.

Conditions

You can also qualify your mappings with the methods “unless” and “when”. For example, if you do not want to translate mappings that lack a value, simply add an “unless” method:

m.map(:from => "foo/bar", :to => "bar/foo").unless(:empty)

if the value at “foo/bar” is empty or nil, “foo/bar” will not be translated. Additionally, if your qualification is more complicated than a simple empty? or nil?, use the “when” method, which takes a block. The mapping:

m.map(:from => "foo/bar", :to => "bar/foo").when do |value|
  value =~ /^M/
end

will only translate if the value at “foo/bar” begins with a capital “M”.

Customized mappings

Ptolemy provides a few powerful ways of handling customized mappings.

.to

If your target mapping depends upon one or more conditions, you may use the .to method which takes a block. The block yields the value of the source mapping for you to evaluate any conditions necessary.

m.from("foo/bar").to do |value|
  if(value == "baz")
    "value/is/baz"
  else
    "value/is/something/else"
  end
end

The above mapping, for example, will use “value/is/baz” as its target mapping if the source value is “baz”, otherwise, the mapping defaults to “value/is/something/else”. (Note that the .to method must be used in conjunction with .from, which takes a simple string for the source mapping.)

.customize

If you have a complex mapping and need to customize it in some way, use the .customize method and pass it a block. The block yields the source object for you to manipulate. Let’s say you’re mapping xml to a hash where the xml source looks like:

<statuses><status><code>Foo</code><message>Bar</message></status></statuses>

You need to map statuses so that the output looks like [{“name” => “Foo”, “text” => “Bar”}]. Here’s how you could customize your mapping:

m.map(:from => "statuses", :to => "status_code").customize do |node|
  res = []
  node.elements.map {|nd| res << {"name" => nd.child_content("code"), "text" => nd.child_content("message")}
  res
end

This mapping would produce:

{"status_code" => [{"name" => "Foo", "text" => "Bar"}]}

A more common use case is concatenation of nested xml nodes. Given the following xml:

<institutions><institution>FOO</institution><institution>BAR</institution><institution>BAZ</institution></institutions>

You could easily concatentate the institutions nested within the <institutions> node with the following mapping:

m.map(:from => "institutions", :to => "concatenated_institutions").customize do |node|
  node.concatenate_children("|")
end

This mapping would produce

{"concatenated_institutions" => "FOO|BAR|BAZ"}

(note: ‘concatentate’ is a convenience method I’ve added to the libxml XML::Node object)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.