Skip to content

Commit

Permalink
Merge pull request #13 from leifg/define_json_format
Browse files Browse the repository at this point in the history
Introduce format for morfer
  • Loading branch information
leifg committed Apr 27, 2015
2 parents aeba5ed + e5714af commit ba50939
Show file tree
Hide file tree
Showing 18 changed files with 847 additions and 361 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
3. Commit your changes (`git commit -am "Add some feature"`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
22 changes: 11 additions & 11 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
source 'https://rubygems.org'
source "https://rubygems.org"

# Specify your gem's dependencies in morfo.gemspec
gemspec

group :test, :development do
gem 'coveralls', require: false
gem 'guard'
gem 'guard-rspec'
gem 'simplecov'
gem 'pry'
gem 'rubinius-coverage', platform: :rbx
gem "coveralls", require: false
gem "guard"
gem "guard-rspec"
gem "simplecov"
gem "pry"
gem "rubinius-coverage", platform: :rbx

gem 'rb-inotify', require: false
gem 'rb-fsevent', require: false
gem 'rb-fchange', require: false
gem "rb-inotify", require: false
gem "rb-fsevent", require: false
gem "rb-fchange", require: false
end

gem 'json'
gem "json"
4 changes: 2 additions & 2 deletions Guardfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# A sample Guardfile
# More info at https://github.com/guard/guard#readme

guard :rspec, cmd: 'bundle exec rspec', all_on_start: true do
guard :rspec, cmd: "bundle exec rspec", all_on_start: true do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { 'spec' }
watch("spec/spec_helper.rb") { "spec" }
end
244 changes: 180 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This gem is currently only tested on Ruby 2.0 (including 2.0 mode of JRuby and R

Add this line to your application's Gemfile:

gem 'morfo'
gem "morfo"

And then execute:

Expand All @@ -32,83 +32,199 @@ Use the `field` method to specify what fields exist and where they will get thei

The most basic form is copying the value from another field.

class Title < Morfo::Base
field(:tv_show_title)from(:title)
end
```ruby
class Title < Morfo::Base
field(:tv_show_title)from(:title)
end
```

Afterwards use the `morf` method to morf all hashes in one array to the end result:

Title.morf([
{title: 'The Walking Dead'} ,
{title: 'Breaking Bad'},
])
```ruby
Title.morf([
{ title: "The Walking Dead" },
{ title: "Breaking Bad" },
])

# [
# {tv_show_title: 'The Walking Dead'},
# {tv_show_title: 'Breaking Bad'},
# ]
# [
# { tv_show_title: "The Walking Dead" },
# { tv_show_title: "Breaking Bad" },
# ]
```

If you want to have access to nested values, just provide the path to that field comma separated.


class Name < Morfo::Base
field(:first_name).from(:name, :first)
field(:last_name).from(:name, :last)
end

Name.morf([
{
name: {
first: 'Clark',
last: 'Kent',
},
},
{
name: {
first: 'Bruce',
last: 'Wayne',
},
},
])

# [
# {first_name: 'Clark',last_name: 'Kent'},
# {first_name: 'Bruce',last_name: 'Wayne'},
# ]

## Transformations
```ruby
class Name < Morfo::Base
field(:first_name).from(:name, :first)
field(:last_name).from(:name, :last)
end

Name.morf([
{
name: {
first: "Clark",
last: "Kent",
},
},
{
name: {
first: "Bruce",
last: "Wayne",
},
},
])

# [
# { first_name: "Clark", last_name: "Kent" },
# { first_name: "Bruce", last_name: "Wayne" },
# ]
```

### Transformations

It's also possible to transform the value in any way ruby lets you transform a value. just provide a block in the `transformed` method.

class AndZombies < Morfo::Base
field(:title).from(title).transformed {|title| "#{title} and Zombies"}
end
```ruby
class AndZombies < Morfo::Base
field(:title).from(title).transformed {|title| "#{title} and Zombies"}
end

AndZombies.morf([
{title: 'Pride and Prejudice'},
{title: 'Fifty Shades of Grey'},
])
AndZombies.morf([
{ title: "Pride and Prejudice" },
{ title: "Fifty Shades of Grey" },
])

# [
# {title: 'Pride and Prejudice and Zombies'},
# {title: 'Fifty Shades of Grey and Zombies'},
# ]
# [
# { title: "Pride and Prejudice and Zombies" },
# { title: "Fifty Shades of Grey and Zombies" },
# ]
```

## Calculations
### Calculations

If the value of your field should be based on multiple fields of the input row, yoy can specify a calculation block via the `calculated` method. As an argument the whole input row is passed in.

class NameConcatenator < Morfo::Base
field(:name).calculated {|row| "#{row[:first_name]} #{row[:last_name]}"}
field(:status).calculated {'Best Friend'}
end

NameConcatenator.morf([
{first_name: 'Robin', last_name: 'Hood'},
{first_name: 'Sherlock', last_name: 'Holmes'},
])
```ruby
class NameConcatenator < Morfo::Base
field(:name).calculated {|row| "#{row[:first_name]} #{row[:last_name]}"}
field(:status).calculated {"Best Friend"}
end

NameConcatenator.morf([
{ first_name: "Robin", last_name: "Hood" },
{ first_name: "Sherlock", last_name: "Holmes" },
])

# [
# { name: "Robin Hood", status: "Best Friend" },
# { name: "Sherlock Holmes", status: "Best Friend" }
# ]
```

### Builder

On top of creating transformers with Ruby classes, it is also possible to build transformers with a hash syntax (which could then be serialized as json and stored somewhere else).

```ruby
morfer = Morfo::Builder.new([
{ field: :first_name, from: [:name, :first] },
{ field: :last_name, from: [:name, :last] },
])

morfer.morf([
{
name: {
first: "Clark",
last: "Kent",
},
},
{
name: {
first: "Bruce",
last: "Wayne",
},
},
])

# [
# { first_name: "Clark", last_name: "Kent" },
# { first_name: "Bruce", last_name: "Wayne" },
# ]
```

The builder includes all other features such as calculation and transformation

#### Builder Transformations

To transform a value, use the placeholder %{value}

```ruby
class AndZombies < Morfo::Base
field(:title).from(title).transformed {|title| "#{title} and Zombies"}
end

morfer = Morfo::Builder.new([
{ field: :title, from: :title, transformed: "%{title} and Zombies" },
])

morfer.morf([
{ title: "Pride and Prejudice" },
{ title: "Fifty Shades of Grey" },
])

# [
# { title: "Pride and Prejudice and Zombies" },
# { title: "Fifty Shades of Grey and Zombies" },
# ]
```

#### Builder Calculations

To get access to the other fields use the [ruby string format syntax](http://ruby-doc.org/core-2.2.0/String.html#method-i-25).

```ruby
morfer = Morfo::Builder.new([
{ field: :name, calculated: "%{first_name} %{last_name}" },
{ field: :status, calculated: "Best Friend" },
])

morfer.morf([
{ first_name: "Robin", last_name: "Hood" },
{ first_name: "Sherlock", last_name: "Holmes" },
])

# [
# { name: "Robin Hood", status: "Best Friend" },
# { name: "Sherlock Holmes", status: "Best Friend" }
# ]
```

It's even possible to get access to nested keys, using a dot as separator:

```ruby
morfer = Morfo::Builder.new([
{ field: :name, calculated: "%{name.first} %{name.last}" },
])

morfer.morf([
{
name: {
first: "Clark",
last: "Kent",
},
},
{
name: {
first: "Bruce",
last: "Wayne",
},
},
])

# [
# { name: "Clark Kent" },
# { name: "Bruce Wayne" },
# ]
```

# [
# {:name=>"Robin Hood", :status=>"Best Friend"},
# {:name=>"Sherlock Holmes", :status=>'Best Friend'}
# ]
4 changes: 2 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
require "bundler/gem_tasks"
require "rspec/core/rake_task"

RSpec::Core::RakeTask.new(:spec)
20 changes: 10 additions & 10 deletions benchmarks/data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ def nested_wrapper

def row
{
first_name: 'Jazmyn',
last_name: 'Willms',
gender: 'female',
phone_number: '485-675-9228',
cell_phone: '1-172-435-9402 x4907',
street_name: 'Becker Inlet',
street_number: '15a',
city: 'Carolynchester',
zip: '38189',
country: 'USA',
first_name: "Jazmyn",
last_name: "Willms",
gender: "female",
phone_number: "485-675-9228",
cell_phone: "1-172-435-9402 x4907",
street_name: "Becker Inlet",
street_number: "15a",
city: "Carolynchester",
zip: "38189",
country: "USA",
}
end

Expand Down
14 changes: 7 additions & 7 deletions benchmarks/run.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
require 'morfo'
require 'benchmark'
require './benchmarks/data'
require "morfo"
require "benchmark"
require "./benchmarks/data"

iterations = 100
batch_size = 10000

definitions = [
{
label: 'Simple (strings)',
label: "Simple (strings)",
row: BenchmarkData.row_string_keys,
morf_class: BenchmarkData::SimpleMorferString
},
{
label: 'Simple (symbols)',
label: "Simple (symbols)",
row: BenchmarkData.row,
morf_class: BenchmarkData::SimpleMorferSymbol
},
{
label: 'Nested (strings)',
label: "Nested (strings)",
row: BenchmarkData.row_nested_string_keys,
morf_class: BenchmarkData::NestedMorferString
},
{
label: 'Nested (symbols)',
label: "Nested (symbols)",
row: BenchmarkData.row_nested,
morf_class: BenchmarkData::NestedMorferSymbol
},
Expand Down
Loading

0 comments on commit ba50939

Please sign in to comment.