Karta

Karta is a very light-weight Ruby library that makes it easy to create mapper objects in a Ruby application. The mapper object makes it easy to map or transform one object into an other. The main use case is to transform data objects from an domain to another domain, e.g. map a Twitter::User to User. Instead of having to, for example, define a method #from_twitter_user on the User class which sets all attributes correctly a mapper object is created which defines all mappings.

Installation

Add this line to your application's Gemfile:

gem 'karta'

And then execute:

$ bundle

Or install it yourself as:

$ gem install karta

Usage

Setting up a mapper

The main functionality of Karta is used by letting a class inherit from Karta::Mapper. By doing so the class gets a #map method which will run all methods starting with map_ with the two objects as arguments.

Example
class MyTwitterMapper < Karta::Mapper
  def map_email(twitter_user, user)
    user.email = twitter_user.twitter_email
  end

  def map_username(twitter_user, user)
    user.username = twitter_user.twitter_handle.gsub('@', '')
  end
end

# Mapping from one instance to another, overriding
# values if already set
twitter_user = ...
user = ...
mapped_user = MyTwitterMapper.new.map(from: twitter_user, to: user)

# Mapping from an instance to a class, will return
# a new instance of the class
twitter_user = ...
user = MyTwitterMapper.new.map(from: twitter_user, to: User)

# Using class method (which instantiates before running map on the instance)
twitter_user = ...
user = MyTwitterMapper.map(from: twitter_user, to: User)

Using the mapper registry

To simplify cases when an application has several mappers it is possible to register mappers and then only use Karta.map to map between two objects.

Example
class MyMapper < Karta::Mapper
  # map methods...
end

Karta.register_mapper MyMapper, from_klass: Twitter::User, to_klass: User

# There is an option to not have to specify from and to class
# when registering the mapper. This relies on reflection and
# requires the mapper to have a class name on the correct format
# (`[from class]To[to class]Mapper`) for example `FooToBarMapper`.
class FooToBarMapper < Karta::Mapper
  # map methods
end

# Register mapper with from_klass = Foo and to_klass = Bar
Karta.register_mapper FooToBarMapper

# Using Karta.map to map between two objects
twitter_user = ...
user = Karta.map(from: twitter_user, to: User)

foo = ...
bar = Karta.map(from: foo, to Bar)

One to one mappings

Sometimes you have fields that could be mapped directly without performing any transformations instead of having to define mapping methods for each you can use one_to_one_mapping :attr.

Example
class FooToBarMapper < Karta::Mapper
  one_to_one_mapping :email
end

foo = ...
bar = FooToBarMapper.map(from: foo, to Bar)
puts foo.email == bar.email # => true

Contributing

  1. Fork it ( https://github.com/samuel02/karta/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request