morfo 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +37 -56
- data/benchmarks/data.rb +74 -0
- data/benchmarks/run.rb +46 -0
- data/lib/morfo/actions/base.rb +0 -0
- data/lib/morfo/actions.rb +56 -0
- data/lib/morfo/version.rb +1 -1
- data/lib/morfo.rb +11 -41
- data/spec/lib/morfo_spec.rb +77 -23
- metadata +6 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7bb20ae90a7b011588d8e096694b69fab5664684
         | 
| 4 | 
            +
              data.tar.gz: 00b3eb367ac96a797105118974ca2562a35d4163
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c84f9323b71740ee3056033a25974a7daefedd3e29e92b40138bf5591e1b3a186349527d4cf13865c8a91bcbd260f01587857917dae74eca157351250de3f321
         | 
| 7 | 
            +
              data.tar.gz: d052cce267ede1514bb6bb70c2db3eabbc3c4f01273d337c95b399986a683f0516ea2175fc43b0ad6fbf9003a1789fc62054ac498d6cc5747a886c564985db9e
         | 
    
        data/README.md
    CHANGED
    
    | @@ -2,9 +2,7 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            [](https://travis-ci.org/leifg/morfo) [](https://coveralls.io/r/leifg/morfo) [](https://codeclimate.com/github/leifg/morfo) [](https://gemnasium.com/leifg/morfo) [](http://badge.fury.io/rb/morfo)
         | 
| 4 4 |  | 
| 5 | 
            -
            This  | 
| 6 | 
            -
             | 
| 7 | 
            -
            But instead of importing spreadsheets into models, you can morf (typo intended) arrays of Hashes into other arrays of hashes.
         | 
| 5 | 
            +
            This gem acts like a universal converter from hashes into other hashes. You just define where your hash should get its data from and morfo will do the rest for you.
         | 
| 8 6 |  | 
| 9 7 | 
             
            ## Compatibility
         | 
| 10 8 |  | 
| @@ -28,10 +26,14 @@ Or install it yourself as: | |
| 28 26 |  | 
| 29 27 | 
             
            In order to morf the hashes you have to provide a class that extends `Morf::Base`
         | 
| 30 28 |  | 
| 31 | 
            -
            Use the ` | 
| 29 | 
            +
            Use the `field` method to specify what fields exist and where they will get their data from:
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            ### Simple Mapping
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            The most basic form is, just define another field from the input hash. The value will just be copied.
         | 
| 32 34 |  | 
| 33 35 | 
             
                class Title < Morfo::Base
         | 
| 34 | 
            -
                   | 
| 36 | 
            +
                  field :tv_show_title, from: :title
         | 
| 35 37 | 
             
                end
         | 
| 36 38 |  | 
| 37 39 | 
             
            Afterwards use the `morf` method to morf all hashes in one array to the end result:
         | 
| @@ -46,50 +48,12 @@ Afterwards use the `morf` method to morf all hashes in one array to the end resu | |
| 46 48 | 
             
                #   {tv_show_title: 'Breaking Bad'},
         | 
| 47 49 | 
             
                # ]
         | 
| 48 50 |  | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
                class MultiTitle < Morfo::Base
         | 
| 52 | 
            -
                  map :title, :tv_show_title
         | 
| 53 | 
            -
                  map :title, :show_title
         | 
| 54 | 
            -
                end
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                MultiTitle.morf([
         | 
| 57 | 
            -
                          {title: 'The Walking Dead'} ,
         | 
| 58 | 
            -
                          {title: 'Breaking Bad'},
         | 
| 59 | 
            -
                        ])
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                # [
         | 
| 62 | 
            -
                #   {tv_show_title: 'The Walking Dead', show_title: 'The Walking Dead'},
         | 
| 63 | 
            -
                #   {tv_show_title: 'Breaking Bad', show_title: 'Breaking Bad'},
         | 
| 64 | 
            -
                # ]
         | 
| 65 | 
            -
             | 
| 66 | 
            -
            ## Transformations
         | 
| 67 | 
            -
             | 
| 68 | 
            -
            For each mapping you can define a block, that will be called on every input:
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                class AndZombies < Morfo::Base
         | 
| 71 | 
            -
                  map :title, :title do |title|
         | 
| 72 | 
            -
                    "#{title} and Zombies"
         | 
| 73 | 
            -
                  end
         | 
| 74 | 
            -
                end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                AndZombies.morf([
         | 
| 77 | 
            -
                      {title: 'Pride and Prejudice'},
         | 
| 78 | 
            -
                      {title: 'Fifty Shades of Grey'},
         | 
| 79 | 
            -
                    ])
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                # [
         | 
| 82 | 
            -
                #     {title: 'Pride and Prejudice and Zombies'},
         | 
| 83 | 
            -
                #     {title: 'Fifty Shades of Grey and Zombies'},
         | 
| 84 | 
            -
                # ]
         | 
| 85 | 
            -
             | 
| 86 | 
            -
            ## Nested Values
         | 
| 51 | 
            +
            If you want to have access to nested values, you'll have to provide an array as the key:
         | 
| 87 52 |  | 
| 88 | 
            -
            You can directly access nested values in the hashes:
         | 
| 89 53 |  | 
| 90 54 | 
             
                class Name < Morfo::Base
         | 
| 91 | 
            -
                   | 
| 92 | 
            -
                   | 
| 55 | 
            +
                  field :first_name, from: [:name, :first]
         | 
| 56 | 
            +
                  field :last_name, from: [:name, :last]
         | 
| 93 57 | 
             
                end
         | 
| 94 58 |  | 
| 95 59 | 
             
                Name.morf([
         | 
| @@ -112,22 +76,39 @@ You can directly access nested values in the hashes: | |
| 112 76 | 
             
                #     {first_name: 'Bruce',last_name: 'Wayne'},
         | 
| 113 77 | 
             
                # ]
         | 
| 114 78 |  | 
| 79 | 
            +
            ## Transformations
         | 
| 115 80 |  | 
| 116 | 
            -
             | 
| 81 | 
            +
            Every field can also take a transformation block, so that the original input can be transformed.
         | 
| 117 82 |  | 
| 118 | 
            -
                class  | 
| 119 | 
            -
                   | 
| 120 | 
            -
                  map :last_name, [:superhero, :name, :last]
         | 
| 83 | 
            +
                class AndZombies < Morfo::Base
         | 
| 84 | 
            +
                  field(:title, from: :title) {|title| "#{title} and Zombies"}
         | 
| 121 85 | 
             
                end
         | 
| 122 86 |  | 
| 123 | 
            -
                 | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 87 | 
            +
                AndZombies.morf([
         | 
| 88 | 
            +
                      {title: 'Pride and Prejudice'},
         | 
| 89 | 
            +
                      {title: 'Fifty Shades of Grey'},
         | 
| 90 | 
            +
                    ])
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                # [
         | 
| 93 | 
            +
                #     {title: 'Pride and Prejudice and Zombies'},
         | 
| 94 | 
            +
                #     {title: 'Fifty Shades of Grey and Zombies'},
         | 
| 95 | 
            +
                # ]
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            As the second argument, the whole row is passed into the block. So you can even do transformation based on the whole row. Or you can leave out all the arguments and return a static value.
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                class NameConcatenator < Morfo::Base
         | 
| 100 | 
            +
                  field(:name) {|_, row| "#{row[:first_name]} #{row[:last_name]}"}
         | 
| 101 | 
            +
                  field(:status) { 'Best Friend' }
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                NameConcatenator.morf([
         | 
| 105 | 
            +
                      {first_name: 'Robin', last_name: 'Hood'},
         | 
| 106 | 
            +
                      {first_name: 'Sherlock', last_name: 'Holmes'},
         | 
| 107 | 
            +
                    ])
         | 
| 127 108 |  | 
| 128 109 | 
             
                # [
         | 
| 129 | 
            -
                #   { | 
| 130 | 
            -
                #   { | 
| 110 | 
            +
                #   {:name=>"Robin Hood", :status=>"Best Friend"},
         | 
| 111 | 
            +
                #   {:name=>"Sherlock Holmes", :status=>'Best Friend'}
         | 
| 131 112 | 
             
                # ]
         | 
| 132 113 |  | 
| 133 114 |  | 
    
        data/benchmarks/data.rb
    ADDED
    
    | @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            module BenchmarkData
         | 
| 2 | 
            +
              extend self
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              def nested_wrapper
         | 
| 5 | 
            +
                :person
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              def row
         | 
| 9 | 
            +
                {
         | 
| 10 | 
            +
                  first_name: 'Jazmyn',
         | 
| 11 | 
            +
                  last_name: 'Willms',
         | 
| 12 | 
            +
                  gender: 'female',
         | 
| 13 | 
            +
                  phone_number: '485-675-9228',
         | 
| 14 | 
            +
                  cell_phone: '1-172-435-9402 x4907',
         | 
| 15 | 
            +
                  street_name: 'Becker Inlet',
         | 
| 16 | 
            +
                  street_number: '15a',
         | 
| 17 | 
            +
                  city: 'Carolynchester',
         | 
| 18 | 
            +
                  zip: '38189',
         | 
| 19 | 
            +
                  country: 'USA',
         | 
| 20 | 
            +
                }
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              def row_string_keys
         | 
| 24 | 
            +
                stringify_keys(row)
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              def row_nested
         | 
| 28 | 
            +
                {
         | 
| 29 | 
            +
                  nested_wrapper => row
         | 
| 30 | 
            +
                }
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              def row_nested_string_keys
         | 
| 34 | 
            +
                {
         | 
| 35 | 
            +
                  nested_wrapper.to_s => row_string_keys
         | 
| 36 | 
            +
                }
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              private
         | 
| 40 | 
            +
              def stringify_keys hash
         | 
| 41 | 
            +
                hash.keys.each do |key|
         | 
| 42 | 
            +
                  hash[key.to_s] = hash.delete(key)
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
                hash
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              class SimpleMorferSymbol < Morfo::Base
         | 
| 48 | 
            +
                BenchmarkData.row.keys.each do |field|
         | 
| 49 | 
            +
                  field(:"#{field}_mapped", from: field)
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              class SimpleMorferString < Morfo::Base
         | 
| 54 | 
            +
                BenchmarkData.row_string_keys.keys.each do |field|
         | 
| 55 | 
            +
                  field("#{field}_mapped", from: field)
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              class NestedMorferSymbol < Morfo::Base
         | 
| 60 | 
            +
                BenchmarkData.row_nested.each do |key, value|
         | 
| 61 | 
            +
                  value.keys.each do |field|
         | 
| 62 | 
            +
                    field(:"#{field}_mapped", from: [key, field])
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              class NestedMorferString < Morfo::Base
         | 
| 68 | 
            +
                BenchmarkData.row_nested_string_keys.each do |key, value|
         | 
| 69 | 
            +
                  value.keys.each do |field|
         | 
| 70 | 
            +
                    field("#{field}_mapped", from: [key, field])
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
            end
         | 
    
        data/benchmarks/run.rb
    ADDED
    
    | @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            require 'morfo'
         | 
| 2 | 
            +
            require 'benchmark'
         | 
| 3 | 
            +
            require './benchmarks/data'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            iterations = 100
         | 
| 6 | 
            +
            batch_size = 10000
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            definitions = [
         | 
| 9 | 
            +
              {
         | 
| 10 | 
            +
                label: 'Simple (strings)',
         | 
| 11 | 
            +
                row: BenchmarkData.row_string_keys,
         | 
| 12 | 
            +
                morf_class: BenchmarkData::SimpleMorferString
         | 
| 13 | 
            +
              },
         | 
| 14 | 
            +
              {
         | 
| 15 | 
            +
                label: 'Simple (symbols)',
         | 
| 16 | 
            +
                row: BenchmarkData.row,
         | 
| 17 | 
            +
                morf_class: BenchmarkData::SimpleMorferSymbol
         | 
| 18 | 
            +
              },
         | 
| 19 | 
            +
              {
         | 
| 20 | 
            +
                label: 'Nested (strings)',
         | 
| 21 | 
            +
                row: BenchmarkData.row_nested_string_keys,
         | 
| 22 | 
            +
                morf_class: BenchmarkData::NestedMorferString
         | 
| 23 | 
            +
              },
         | 
| 24 | 
            +
              {
         | 
| 25 | 
            +
                label: 'Nested (symbols)',
         | 
| 26 | 
            +
                row: BenchmarkData.row_nested,
         | 
| 27 | 
            +
                morf_class: BenchmarkData::NestedMorferSymbol
         | 
| 28 | 
            +
              },
         | 
| 29 | 
            +
            ]
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            definitions.each do |defintition|
         | 
| 32 | 
            +
              defintition.merge!(
         | 
| 33 | 
            +
                data: Array.new(batch_size){ defintition[:row] }
         | 
| 34 | 
            +
                )
         | 
| 35 | 
            +
            end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            Benchmark.bm(20) do |x|
         | 
| 38 | 
            +
              definitions.each do |defintition|
         | 
| 39 | 
            +
                x.report(defintition[:label]) do
         | 
| 40 | 
            +
                  iterations.times do
         | 
| 41 | 
            +
                    defintition[:morf_class].morf(defintition[:data])
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| 46 | 
            +
             | 
| 
            File without changes
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            module Morfo
         | 
| 2 | 
            +
              module Actions
         | 
| 3 | 
            +
                module ValueMethods
         | 
| 4 | 
            +
                  def extract_value from, row
         | 
| 5 | 
            +
                    Array(from).inject(row) do |resulting_value, key|
         | 
| 6 | 
            +
                      resulting_value ? resulting_value[key] : nil
         | 
| 7 | 
            +
                    end
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def store_value to, value
         | 
| 11 | 
            +
                    return {} if value.nil?
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    Array(to).reverse.inject({}) do |hash, key|
         | 
| 14 | 
            +
                      if hash.keys.first.nil?
         | 
| 15 | 
            +
                        hash.merge!(key => value)
         | 
| 16 | 
            +
                      else
         | 
| 17 | 
            +
                        { key => hash }
         | 
| 18 | 
            +
                      end
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                class MapAction
         | 
| 24 | 
            +
                  include ValueMethods
         | 
| 25 | 
            +
                  attr_reader :from
         | 
| 26 | 
            +
                  attr_reader :to
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def initialize from, to
         | 
| 29 | 
            +
                    @from = from
         | 
| 30 | 
            +
                    @to = to
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  def execute row
         | 
| 34 | 
            +
                    store_value(to, extract_value(from, row))
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                class TransformationAction
         | 
| 39 | 
            +
                  include ValueMethods
         | 
| 40 | 
            +
                  attr_reader :to
         | 
| 41 | 
            +
                  attr_reader :from
         | 
| 42 | 
            +
                  attr_reader :transformation
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def initialize from, to, transformation
         | 
| 45 | 
            +
                    @from = from
         | 
| 46 | 
            +
                    @to = to
         | 
| 47 | 
            +
                    @transformation = transformation
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  def execute row
         | 
| 51 | 
            +
                    resulting_value = from ? extract_value(from, row) : nil
         | 
| 52 | 
            +
                    store_value(to, transformation.call(resulting_value,row))
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
    
        data/lib/morfo/version.rb
    CHANGED
    
    
    
        data/lib/morfo.rb
    CHANGED
    
    | @@ -1,9 +1,18 @@ | |
| 1 1 | 
             
            require 'morfo/version'
         | 
| 2 | 
            +
            require 'morfo/actions'
         | 
| 2 3 |  | 
| 3 4 | 
             
            module Morfo
         | 
| 4 5 | 
             
              class Base
         | 
| 5 | 
            -
                def self. | 
| 6 | 
            -
                   | 
| 6 | 
            +
                def self.field field_name, definition={}, &blk
         | 
| 7 | 
            +
                  if blk
         | 
| 8 | 
            +
                    mapping_actions << Morfo::Actions::TransformationAction.new(definition[:from], field_name, blk)
         | 
| 9 | 
            +
                  else
         | 
| 10 | 
            +
                    raise(
         | 
| 11 | 
            +
                      ArgumentError,
         | 
| 12 | 
            +
                      "No field to get value from is specified for #{field_name.inspect}"
         | 
| 13 | 
            +
                    ) unless definition[:from]
         | 
| 14 | 
            +
                    mapping_actions << Morfo::Actions::MapAction.new(definition[:from], field_name)
         | 
| 15 | 
            +
                  end
         | 
| 7 16 | 
             
                end
         | 
| 8 17 |  | 
| 9 18 | 
             
                def self.morf input
         | 
| @@ -31,43 +40,4 @@ module Morfo | |
| 31 40 | 
             
                  hash
         | 
| 32 41 | 
             
                end
         | 
| 33 42 | 
             
              end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
              class MapAction
         | 
| 36 | 
            -
                attr_reader :from
         | 
| 37 | 
            -
                attr_reader :to
         | 
| 38 | 
            -
                attr_reader :transformation
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                def initialize from, to, transformation
         | 
| 41 | 
            -
                  @from = from
         | 
| 42 | 
            -
                  @to = to
         | 
| 43 | 
            -
                  @transformation = transformation
         | 
| 44 | 
            -
                end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                def execute row
         | 
| 47 | 
            -
                  resulting_value = apply_transformation(extract_value(row))
         | 
| 48 | 
            -
                  resulting_value ? store_value(to, resulting_value) : {}
         | 
| 49 | 
            -
                end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                private
         | 
| 52 | 
            -
                def extract_value row
         | 
| 53 | 
            -
                  Array(from).inject(row) do |resulting_value, key|
         | 
| 54 | 
            -
                    resulting_value ? resulting_value[key] : nil
         | 
| 55 | 
            -
                  end
         | 
| 56 | 
            -
                end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                def apply_transformation row
         | 
| 59 | 
            -
                  transformation ? transformation.call(row) : row
         | 
| 60 | 
            -
                end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                def store_value to, value
         | 
| 63 | 
            -
                  Array(to).reverse.inject({}) do |hash, key|
         | 
| 64 | 
            -
                    if hash.keys.first.nil?
         | 
| 65 | 
            -
                      hash.merge!(key => value)
         | 
| 66 | 
            -
                    else
         | 
| 67 | 
            -
                      { key => hash }
         | 
| 68 | 
            -
                    end
         | 
| 69 | 
            -
                  end
         | 
| 70 | 
            -
                  #{ to => value }
         | 
| 71 | 
            -
                end
         | 
| 72 | 
            -
              end
         | 
| 73 43 | 
             
            end
         | 
    
        data/spec/lib/morfo_spec.rb
    CHANGED
    
    | @@ -31,12 +31,24 @@ describe Morfo::Base do | |
| 31 31 | 
             
              end
         | 
| 32 32 |  | 
| 33 33 | 
             
              describe '#morf' do
         | 
| 34 | 
            +
                context 'errors' do
         | 
| 35 | 
            +
                  subject(:no_from) do
         | 
| 36 | 
            +
                    class NilMorfer < Morfo::Base
         | 
| 37 | 
            +
                      field :my_field, {}
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                    NilMorfer
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                  it 'raises error for nil field' do
         | 
| 42 | 
            +
                    expect{no_from.morf([])}.to raise_error(ArgumentError)
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 34 46 | 
             
                context '1 to 1 conversion' do
         | 
| 35 47 | 
             
                  subject do
         | 
| 36 | 
            -
                    class  | 
| 37 | 
            -
                       | 
| 48 | 
            +
                    class TitleMorfer < Morfo::Base
         | 
| 49 | 
            +
                      field :tv_show_title, from: :title
         | 
| 38 50 | 
             
                    end
         | 
| 39 | 
            -
                     | 
| 51 | 
            +
                    TitleMorfer
         | 
| 40 52 | 
             
                  end
         | 
| 41 53 |  | 
| 42 54 | 
             
                  it 'maps title correctly' do
         | 
| @@ -53,12 +65,10 @@ describe Morfo::Base do | |
| 53 65 |  | 
| 54 66 | 
             
                context '1 to 1 conversion with transformation' do
         | 
| 55 67 | 
             
                  subject do
         | 
| 56 | 
            -
                    class  | 
| 57 | 
            -
                       | 
| 58 | 
            -
                        cast.size
         | 
| 59 | 
            -
                      end
         | 
| 68 | 
            +
                    class NumCastMorfer < Morfo::Base
         | 
| 69 | 
            +
                      field(:cast_num, from: :cast){|v,r| v.size}
         | 
| 60 70 | 
             
                    end
         | 
| 61 | 
            -
                     | 
| 71 | 
            +
                    NumCastMorfer
         | 
| 62 72 | 
             
                  end
         | 
| 63 73 |  | 
| 64 74 | 
             
                  it 'calls transformation correctly' do
         | 
| @@ -69,11 +79,11 @@ describe Morfo::Base do | |
| 69 79 |  | 
| 70 80 | 
             
                context '1 to many conversion' do
         | 
| 71 81 | 
             
                  subject do
         | 
| 72 | 
            -
                    class  | 
| 73 | 
            -
                       | 
| 74 | 
            -
                       | 
| 82 | 
            +
                    class MutliTitleMorfer < Morfo::Base
         | 
| 83 | 
            +
                      field :title, from: :title
         | 
| 84 | 
            +
                      field :also_title, from: :title
         | 
| 75 85 | 
             
                    end
         | 
| 76 | 
            -
                     | 
| 86 | 
            +
                    MutliTitleMorfer
         | 
| 77 87 | 
             
                  end
         | 
| 78 88 |  | 
| 79 89 | 
             
                  it 'maps title to multiple fields' do
         | 
| @@ -85,17 +95,24 @@ describe Morfo::Base do | |
| 85 95 | 
             
                context 'nested conversion' do
         | 
| 86 96 | 
             
                  context 'nested source' do
         | 
| 87 97 | 
             
                    subject(:valid_path) do
         | 
| 88 | 
            -
                      class  | 
| 89 | 
            -
                         | 
| 98 | 
            +
                      class ImdbRatingMorfer < Morfo::Base
         | 
| 99 | 
            +
                        field :rating, from: [:ratings, :imdb]
         | 
| 100 | 
            +
                      end
         | 
| 101 | 
            +
                      ImdbRatingMorfer
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                    subject(:valid_path_with_transformation) do
         | 
| 105 | 
            +
                      class ImdbRatingMorfer < Morfo::Base
         | 
| 106 | 
            +
                        field(:rating, from: [:ratings, :imdb]){|v| "Rating: #{v}"}
         | 
| 90 107 | 
             
                      end
         | 
| 91 | 
            -
                       | 
| 108 | 
            +
                      ImdbRatingMorfer
         | 
| 92 109 | 
             
                    end
         | 
| 93 110 |  | 
| 94 111 | 
             
                    subject(:invalid_path) do
         | 
| 95 | 
            -
                      class  | 
| 96 | 
            -
                         | 
| 112 | 
            +
                      class InvalidImdbRatingMorfer < Morfo::Base
         | 
| 113 | 
            +
                        field :rating, from: [:very, :long, :path, :that, :might, :not, :exist]
         | 
| 97 114 | 
             
                      end
         | 
| 98 | 
            -
                       | 
| 115 | 
            +
                      InvalidImdbRatingMorfer
         | 
| 99 116 | 
             
                    end
         | 
| 100 117 |  | 
| 101 118 | 
             
                    it 'maps nested attributes' do
         | 
| @@ -103,6 +120,11 @@ describe Morfo::Base do | |
| 103 120 | 
             
                      expect(valid_path.morf(input)).to eq(expected_output)
         | 
| 104 121 | 
             
                    end
         | 
| 105 122 |  | 
| 123 | 
            +
                    it 'maps nested attributes with transformation' do
         | 
| 124 | 
            +
                      expected_output = input.map{|v| {rating: "Rating: #{v[:ratings][:imdb]}"} }
         | 
| 125 | 
            +
                      expect(valid_path_with_transformation.morf(input)).to eq(expected_output)
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
             | 
| 106 128 | 
             
                    it 'doesn\'t raise error for invalid path' do
         | 
| 107 129 | 
             
                      expected_output = [{},{}]
         | 
| 108 130 | 
             
                      expect(invalid_path.morf(input)).to eq(expected_output)
         | 
| @@ -111,11 +133,11 @@ describe Morfo::Base do | |
| 111 133 |  | 
| 112 134 | 
             
                  context 'nested destination' do
         | 
| 113 135 | 
             
                    subject do
         | 
| 114 | 
            -
                      class  | 
| 115 | 
            -
                         | 
| 116 | 
            -
                         | 
| 136 | 
            +
                      class WrapperMorfer < Morfo::Base
         | 
| 137 | 
            +
                        field([:tv_show, :title], from: :title)
         | 
| 138 | 
            +
                        field([:tv_show, :channel], from: :channel){|v| "Channel: #{v}"}
         | 
| 117 139 | 
             
                      end
         | 
| 118 | 
            -
                       | 
| 140 | 
            +
                      WrapperMorfer
         | 
| 119 141 | 
             
                    end
         | 
| 120 142 |  | 
| 121 143 | 
             
                    it 'maps to nested destination' do
         | 
| @@ -123,7 +145,7 @@ describe Morfo::Base do | |
| 123 145 | 
             
                        {
         | 
| 124 146 | 
             
                          tv_show: {
         | 
| 125 147 | 
             
                            title: v[:title],
         | 
| 126 | 
            -
                            channel: v[:channel],
         | 
| 148 | 
            +
                            channel: "Channel: #{v[:channel]}",
         | 
| 127 149 | 
             
                          }
         | 
| 128 150 | 
             
                        }
         | 
| 129 151 | 
             
                      }
         | 
| @@ -131,5 +153,37 @@ describe Morfo::Base do | |
| 131 153 | 
             
                    end
         | 
| 132 154 | 
             
                  end
         | 
| 133 155 | 
             
                end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                context 'calculations' do
         | 
| 158 | 
            +
                  subject do
         | 
| 159 | 
            +
                    class TitlePrefixMorfer < Morfo::Base
         | 
| 160 | 
            +
                      field(:title_with_channel){|v,r| "#{r[:title]}, (#{r[:channel]})"}
         | 
| 161 | 
            +
                    end
         | 
| 162 | 
            +
                    TitlePrefixMorfer
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                  it 'maps calculation correctly' do
         | 
| 166 | 
            +
                    expected_output = input.map{|r|
         | 
| 167 | 
            +
                      {
         | 
| 168 | 
            +
                        title_with_channel: "#{r[:title]}, (#{r[:channel]})"
         | 
| 169 | 
            +
                      }
         | 
| 170 | 
            +
                    }
         | 
| 171 | 
            +
                    expect(subject.morf(input)).to eq(expected_output)
         | 
| 172 | 
            +
                  end
         | 
| 173 | 
            +
                end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                context 'static values' do
         | 
| 176 | 
            +
                  subject do
         | 
| 177 | 
            +
                    class StaticTitleMorfer < Morfo::Base
         | 
| 178 | 
            +
                      field(:new_title){ 'Static Title' }
         | 
| 179 | 
            +
                    end
         | 
| 180 | 
            +
                    StaticTitleMorfer
         | 
| 181 | 
            +
                  end
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                  it 'maps static value correctly' do
         | 
| 184 | 
            +
                    expected_output = input.map{|r| {new_title: 'Static Title'} }
         | 
| 185 | 
            +
                    expect(subject.morf(input)).to eq(expected_output)
         | 
| 186 | 
            +
                  end
         | 
| 187 | 
            +
                end
         | 
| 134 188 | 
             
              end
         | 
| 135 189 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: morfo
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0 | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Leif Gensert
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014-01- | 
| 11 | 
            +
            date: 2014-01-13 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rake
         | 
| @@ -73,7 +73,11 @@ files: | |
| 73 73 | 
             
            - LICENSE.txt
         | 
| 74 74 | 
             
            - README.md
         | 
| 75 75 | 
             
            - Rakefile
         | 
| 76 | 
            +
            - benchmarks/data.rb
         | 
| 77 | 
            +
            - benchmarks/run.rb
         | 
| 76 78 | 
             
            - lib/morfo.rb
         | 
| 79 | 
            +
            - lib/morfo/actions.rb
         | 
| 80 | 
            +
            - lib/morfo/actions/base.rb
         | 
| 77 81 | 
             
            - lib/morfo/version.rb
         | 
| 78 82 | 
             
            - morfo.gemspec
         | 
| 79 83 | 
             
            - spec/lib/morfo_spec.rb
         |