random_attributes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0fb42eebf2719fd9e4eb30962ce7e4f22917ce2a
4
+ data.tar.gz: 315f87390f64da8c27f7a751b575d8a823f24f02
5
+ SHA512:
6
+ metadata.gz: 5459f78ca52131e811ca1fd89d59d0d6b47d0a1782b5779b690346426ba71e315fb4340da30bc6cc07b31e9193cd80405fc2bb2a5d7311f4a0891c670e01badc
7
+ data.tar.gz: d0592a236ec2a26f2693803df620c353d6a3dd739516b9719a3ea78ecfef6f0f49ecd93f734e109089c4c2114e55a5cbbc22a37bbd760611b1d00d766f4d73c6
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in random_attributes.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Rufus Post
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # RandomAttributes
2
+
3
+ Sometimes people give you rubbish data, when they do rather than wiring
4
+ everything up with hundreds of methods you could use RandomAttributes.
5
+
6
+ If mangling crappy data is not your issue you are probably better served by
7
+ something like [virtus](https://github.com/solnic/virtus).
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'random_attributes'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install random_attributes
22
+
23
+ ## Usage
24
+
25
+ Vanilla:
26
+
27
+ ```ruby
28
+ class Foo
29
+ include RandomAttributes
30
+ attribute "fooBar"
31
+ end
32
+
33
+ foo = Foo.parse { "fooBar" => "hello" }
34
+ foo.foo_bar #=> "hello"
35
+ ```
36
+
37
+ Alias:
38
+
39
+ ```ruby
40
+ class Foo
41
+ include RandomAttributes
42
+ attribute "fooBar", alias: :moo_bar
43
+ end
44
+
45
+ foo = Foo.parse { "fooBar" => "hello" }
46
+ foo.moo_bar #=> "hello"
47
+ ```
48
+
49
+ Type casting:
50
+
51
+ ```ruby
52
+ class Foo
53
+ include RandomAttributes
54
+ attribute "fooBar", type: String
55
+ end
56
+
57
+ foo = Foo.parse { "fooBar" => 34 }
58
+ foo.foo_bar #=> "34"
59
+ ```
60
+
61
+ Many possible values:
62
+
63
+ ```ruby
64
+ class Foo
65
+ include RandomAttributes
66
+ attribute ["fooBar", "mooBar"], alias: :foo_bar
67
+ end
68
+
69
+ foo = Foo.parse { "fooBar" => "hello" }
70
+ foo.foo_bar #=> "hello"
71
+
72
+ foo = Foo.parse { "mooBar" => "hello" }
73
+ foo.foo_bar #=> "hello"
74
+ ```
75
+
76
+ Trying another node:
77
+
78
+ ```ruby
79
+ class Foo
80
+ include RandomAttributes
81
+ attribute "parentNode"
82
+ attribute "fooBar", try: :parent_node
83
+ end
84
+
85
+ foo = Foo.parse { "fooBar" => "hello" }
86
+ foo.foo_bar #=> "hello"
87
+
88
+ foo = Foo.parse { "parentNode" => { "fooBar" => "hello" } }
89
+ foo.foo_bar #=> "hello"
90
+ ```
91
+
92
+ Nested within a node:
93
+
94
+ ```ruby
95
+ class Foo
96
+ include RandomAttributes
97
+ attribute "parentNode"
98
+ attribute "fooBar", within: :parent_node
99
+ end
100
+
101
+ foo = Foo.parse { "parentNode" => { "fooBar" => "hello" } }
102
+ foo.foo_bar #=> "hello"
103
+ ```
104
+
105
+ Models:
106
+
107
+ ```ruby
108
+ class Bar
109
+ attr_reader :message
110
+ def initialize message
111
+ @message = message
112
+ end
113
+ end
114
+
115
+ class Foo
116
+ include RandomAttributes
117
+ attribute "fooBar", model: Bar
118
+ end
119
+
120
+ foo = Foo.parse { "fooBar" => "hello" }
121
+ foo.foo_bar.message #=> "hello"
122
+ ```
123
+
124
+ Collections:
125
+
126
+ ```ruby
127
+ class Bar
128
+ attr_reader :message
129
+ def initialize message
130
+ @message = message
131
+ end
132
+ end
133
+
134
+ class Foo
135
+ include RandomAttributes
136
+ attribute "fooBar", collection: Bar
137
+ end
138
+
139
+ foo = Foo.parse { "fooBar" => ["hello", "goodbye"] }
140
+ foo.foo_bar.first.message #=> "hello"
141
+ foo.foo_bar.last.message #=> "goodbye"
142
+ ```
143
+
144
+ Parse data with proc:
145
+
146
+ ```ruby
147
+ class Foo
148
+ include RandomAttributes
149
+ attribute "fooBar", parse: ->(value) { "#{value} from a proc!" }
150
+ end
151
+
152
+ foo = Foo.parse { "fooBar" => "hello" }
153
+ foo.foo_bar #=> "hello from a proc!"
154
+ ```
155
+
156
+ Callbacks:
157
+
158
+ ```ruby
159
+ class Foo
160
+ include RandomAttributes
161
+ attribute "fooBar"
162
+ attribute "multipleFooBar"
163
+
164
+ after_parse :multiply_foo_bar
165
+
166
+ def multiply_foo_bar
167
+ set_attribute :multiple_foo_bar, foo_bar * 2
168
+ end
169
+ end
170
+
171
+ foo = Foo.parse { "fooBar" => 2 }
172
+ foo.multiple_foo_bar #=> 4
173
+ ```
174
+
175
+ ## Contributing
176
+
177
+ 1. Fork it
178
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
179
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
180
+ 4. Push to the branch (`git push origin my-new-feature`)
181
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ module RandomAttributes
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,200 @@
1
+ require "random_attributes/version"
2
+ require "active_support/concern"
3
+ require "active_support/callbacks"
4
+
5
+ # RandomAttributes
6
+ #
7
+ # Getters, setters and object building for a someone elses data structure.
8
+ #
9
+ # Example:
10
+ #
11
+ # class Runner
12
+ # include RandomAttributes
13
+ # attribute 'runnerName', alias: :name
14
+ # end
15
+ #
16
+ # runner = Runner.new "runnerName" => "Phar Lap"
17
+ # runner.name #=> "Phar Lap"
18
+ #
19
+ module RandomAttributes
20
+ extend ActiveSupport::Concern
21
+ include ActiveSupport::Callbacks
22
+
23
+ class Register
24
+ class AliasError < StandardError; end
25
+
26
+ attr_reader :originals, :aliased, :type, :parent_node, :try_node
27
+
28
+ def initialize(attrs, options = {})
29
+
30
+ if attrs.is_a?(Array)
31
+ raise AliasError, "if you want to alias attributes you need to specify the alias in the options" unless
32
+ options[:alias].present?
33
+ @aliased = options[:alias].to_s
34
+ else
35
+ @aliased = options[:alias].to_s.presence || attrs.underscore
36
+ attrs = [attrs]
37
+ end
38
+
39
+ @originals = attrs
40
+ @parent_node = options[:within]
41
+ @try_node = options[:try]
42
+
43
+ @type = options[:type]
44
+ @model = options[:model]
45
+ @collection = options[:collection]
46
+ @cast_proc = options[:parse] || cast_to_proc
47
+ end
48
+
49
+ def key
50
+ @originals.join '__'
51
+ end
52
+
53
+ def cast(value)
54
+ @cast_proc.call value
55
+ end
56
+
57
+ private
58
+
59
+ # TODO refactor this.
60
+ def cast_to_proc
61
+ if @type
62
+ ->(value) { value ? Kernel.send(@type.to_s, value) : value }
63
+ elsif @model
64
+ ->(value) { value ? @model.parse(value) : value }
65
+ elsif @collection
66
+ if @collection.respond_to?(:parse)
67
+ ->(value) {
68
+ if value
69
+ value.map do |member|
70
+ member.is_a?(@collection) ? member : @collection.parse(member)
71
+ end
72
+ else
73
+ []
74
+ end
75
+ }
76
+ else
77
+ ->(value) {
78
+ if value
79
+ value.map do |member|
80
+ member.is_a?(@collection) ? member : @collection.new(member)
81
+ end
82
+ else
83
+ []
84
+ end
85
+ }
86
+ end
87
+ else
88
+ ->(value) { value }
89
+ end
90
+ end
91
+ end
92
+
93
+ included do
94
+ define_callbacks :parse
95
+ end
96
+
97
+ module ClassMethods
98
+ def attribute(attrs, options = {})
99
+ register = Register.new attrs, options
100
+
101
+ attribute_register[register.aliased] = register
102
+
103
+ define_method register.aliased do
104
+ get_attribute register
105
+ end
106
+
107
+ define_method :"#{register.aliased}=" do |value|
108
+ set_attribute register.aliased, value
109
+ end
110
+ end
111
+
112
+ def attribute_register
113
+ @_attribute_register ||= {}
114
+ end
115
+
116
+ def parse(attributes)
117
+ new.parse attributes
118
+ end
119
+
120
+ def before_parse(*args, &block)
121
+ set_callback(:parse, :before, *args, &block)
122
+ end
123
+
124
+ def after_parse(*args, &block)
125
+ set_callback(:parse, :after, *args, &block)
126
+ end
127
+ end
128
+
129
+ def initialize(attrs = nil)
130
+ parse attrs
131
+ end
132
+
133
+ def cache_key
134
+ @raw_attributes_hash
135
+ end
136
+
137
+ def parse(attrs = nil)
138
+ @parsed_attributes = {}
139
+ attrs && attrs.stringify_keys!
140
+ run_callbacks :parse do
141
+ @raw_attributes = attributes.merge(attrs.nil? ? {} : attrs).freeze
142
+ @raw_attributes_hash = Digest::MD5.hexdigest(attributes.to_s)
143
+ end
144
+ self
145
+ end
146
+
147
+ alias :merge_attributes :parse
148
+
149
+ def attributes
150
+ @raw_attributes ||= {}.freeze
151
+ end
152
+
153
+ private
154
+
155
+ def parsed_attributes
156
+ @parsed_attributes ||= {}
157
+ end
158
+
159
+ def get_attribute(register)
160
+ if parsed_attributes.key?(register.aliased)
161
+ parsed_attributes[register.aliased]
162
+ else
163
+ parsed_attributes[register.aliased] = _get_attribute(register)
164
+ end
165
+ end
166
+
167
+ def set_attribute(key, value)
168
+ parsed_attributes[key.to_s] = value
169
+ end
170
+
171
+ def _search_originals(register, node, value = nil)
172
+ register.originals.each do |key|
173
+ break if value = node[key]
174
+ end
175
+ value
176
+ end
177
+
178
+ def _get_attribute(register)
179
+
180
+ value = attributes[register.aliased]
181
+
182
+ unless value
183
+ if register.try_node
184
+ if try_node = send(register.try_node)
185
+ value = _search_originals register, try_node
186
+ else
187
+ value = _search_originals register, attributes
188
+ end
189
+ elsif register.parent_node
190
+ if parent_node = send(register.parent_node)
191
+ value = _search_originals register, parent_node
192
+ end
193
+ else
194
+ value = _search_originals register, attributes
195
+ end
196
+ end
197
+
198
+ register.cast(value)
199
+ end
200
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'random_attributes/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "random_attributes"
8
+ spec.version = RandomAttributes::VERSION
9
+ spec.authors = ["Rufus Post"]
10
+ spec.email = ["rufuspost@gmail.com"]
11
+ spec.description = %q{When someone gives you rubbish data an you want to map it to something else.}
12
+ spec.summary = %q{Data hash to object mapper}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "active_support", ">= 3.0"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec", "~> 2.14"
26
+ spec.add_development_dependency "ffaker"
27
+ end
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+ require 'active_support/core_ext/hash'
3
+ require 'ffaker'
4
+
5
+ class TestAttributeThing
6
+ include RandomAttributes
7
+
8
+ attribute 'name'
9
+ end
10
+
11
+ class TestAttributeCasting
12
+ include RandomAttributes
13
+
14
+ attribute 'name'
15
+ attribute 'venue', type: String
16
+ attribute 'fooName', alias: :bar_name
17
+ attribute 'raceIdentifier', alias: :identifier, type: String
18
+ attribute 'number', type: Integer
19
+ attribute 'stake', type: Float
20
+ attribute ['fooMeeting', 'barMeeting'], alias: :meeting
21
+ attribute 'manyThings', collection: TestAttributeThing
22
+ attribute 'singleThing', model: TestAttributeThing
23
+ attribute 'someDetails', alias: :details
24
+ attribute 'nestedDetail', within: :details
25
+ attribute ['status', 'raceStatus'], alias: :status, try: :details
26
+ attribute 'afterParseValue'
27
+ attribute 'afterOptions', parse: ->(value) { "#{value} after parse!" }
28
+
29
+ after_parse :change_value
30
+
31
+ def change_value
32
+ # We have to use this method here because I can't figure out why the
33
+ # dynamic method is not working.
34
+ set_attribute :after_parse_value, 'after parse!'
35
+ end
36
+ end
37
+
38
+ describe RandomAttributes do
39
+ let(:string) {
40
+ Faker::Name.name
41
+ }
42
+
43
+ it "should default to given type" do
44
+ subject = TestAttributeCasting.parse 'name' => string
45
+ subject.name.should eq string
46
+ end
47
+
48
+ it "should cast strings and rename attribute" do
49
+ subject = TestAttributeCasting.parse 'venue' => string
50
+ subject.venue.should be_a(String)
51
+ end
52
+
53
+ it "should cast floats" do
54
+ subject = TestAttributeCasting.parse 'stake' => '1.5'
55
+ subject.stake.should be_a(Float)
56
+ end
57
+
58
+ it "should cast integers" do
59
+ subject = TestAttributeCasting.parse 'number' => '10'
60
+ subject.number.should be_a(Integer)
61
+ end
62
+
63
+ it "should rename attributes" do
64
+ subject = TestAttributeCasting.parse 'raceIdentifier' => string
65
+ subject.identifier.should eq string
66
+ end
67
+
68
+ it "should create setter method" do
69
+ subject = TestAttributeCasting.parse 'raceIdentifier' => string
70
+ subject.identifier = 'Matamata'
71
+ subject.identifier.should eq 'Matamata'
72
+ end
73
+
74
+ it "should try many attributes" do
75
+ subject = TestAttributeCasting.parse 'fooMeeting' => nil, 'barMeeting' => string
76
+ subject.meeting.should eq string
77
+ end
78
+
79
+ it "should try a collection" do
80
+ subject = TestAttributeCasting.parse 'manyThings' => [{ "name" => string}]
81
+ subject.many_things.first.name.should eq string
82
+ end
83
+
84
+ it "should just return element if already a collection member" do
85
+ subject = TestAttributeCasting.parse 'manyThings' => [TestAttributeThing.new(name: string)]
86
+ subject.many_things.first.name.should eq string
87
+ end
88
+
89
+ it "should memoize instance variables" do
90
+ subject = TestAttributeCasting.parse 'manyThings' => [{ "name" => string}]
91
+ subject.many_things.first.object_id.should eq subject.many_things.first.object_id
92
+ end
93
+
94
+ it "should return an array if collection nil" do
95
+ subject = TestAttributeCasting.parse 'manyThings' => nil
96
+ subject.many_things.should be_a(Array)
97
+ end
98
+
99
+ it "should try a member" do
100
+ subject = TestAttributeCasting.parse 'singleThing' => { "name" => string}
101
+ subject.single_thing.name.should eq string
102
+ end
103
+
104
+ it "should assign something one deep" do
105
+ subject = TestAttributeCasting.parse 'someDetails' => { 'nestedDetail' => string }
106
+ subject.nested_detail.should eq string
107
+ end
108
+
109
+ it "should try other places for the data" do
110
+ subject = TestAttributeCasting.parse 'someDetails' => { 'raceStatus' => string }
111
+ subject.status.should eq string
112
+
113
+ subject = TestAttributeCasting.parse 'raceStatus' => string
114
+ subject.status.should eq string
115
+
116
+ subject = TestAttributeCasting.parse 'status' => string
117
+ subject.status.should eq string
118
+ end
119
+
120
+ it "should return the aliased value if present" do
121
+ subject = TestAttributeCasting.parse "bar_name" => string
122
+ subject.bar_name.should eq string
123
+ end
124
+
125
+ it "should call the after parse method" do
126
+ subject = TestAttributeCasting.parse "afterParseValue" => string
127
+ subject.after_parse_value.should eq "after parse!"
128
+ end
129
+
130
+ it "should add a callback from the options hash" do
131
+ subject = TestAttributeCasting.parse "afterOptions" => string
132
+ subject.after_options.should eq "#{string} after parse!"
133
+ end
134
+
135
+ it "should clear memoized data when parsed is called" do
136
+ subject = TestAttributeCasting.new
137
+
138
+ subject.name.should be_nil
139
+
140
+ subject = TestAttributeCasting.parse 'name' => string
141
+ subject.name.should eq string
142
+ end
143
+
144
+ it "should have instance method parse methods" do
145
+ subject = TestAttributeCasting.new
146
+
147
+ subject.parse 'name' => 'foo'
148
+ subject.name.should eq 'foo'
149
+
150
+ subject.merge_attributes 'name' => 'bar'
151
+ subject.name.should eq 'bar'
152
+ end
153
+
154
+ it "should return a reliable cache key" do
155
+ subject = TestAttributeThing.parse 'name' => 'foo'
156
+ subject.cache_key.should eq "c9e2bd1b9e2ee9b862a8f035e4ec9d57"
157
+ end
158
+
159
+ it "should return the original raw attributes hash as a cache key" do
160
+ subject_one = TestAttributeThing.parse 'name' => 'foo'
161
+ subject_two = TestAttributeThing.parse 'name' => 'foo'
162
+ subject_one.cache_key.should eq subject_two.cache_key
163
+ end
164
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'random_attributes'
5
+
6
+ RSpec.configure do |config|
7
+ config.order = 'random'
8
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: random_attributes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rufus Post
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2013-12-16 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: active_support
16
+ prerelease: false
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: "3.0"
22
+ type: :runtime
23
+ version_requirements: *id001
24
+ - !ruby/object:Gem::Dependency
25
+ name: bundler
26
+ prerelease: false
27
+ requirement: &id002 !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ~>
30
+ - !ruby/object:Gem::Version
31
+ version: "1.3"
32
+ type: :development
33
+ version_requirements: *id002
34
+ - !ruby/object:Gem::Dependency
35
+ name: rake
36
+ prerelease: false
37
+ requirement: &id003 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - &id005
40
+ - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ type: :development
44
+ version_requirements: *id003
45
+ - !ruby/object:Gem::Dependency
46
+ name: rspec
47
+ prerelease: false
48
+ requirement: &id004 !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ~>
51
+ - !ruby/object:Gem::Version
52
+ version: "2.14"
53
+ type: :development
54
+ version_requirements: *id004
55
+ - !ruby/object:Gem::Dependency
56
+ name: ffaker
57
+ prerelease: false
58
+ requirement: &id006 !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - *id005
61
+ type: :development
62
+ version_requirements: *id006
63
+ description: When someone gives you rubbish data an you want to map it to something else.
64
+ email:
65
+ - rufuspost@gmail.com
66
+ executables: []
67
+
68
+ extensions: []
69
+
70
+ extra_rdoc_files: []
71
+
72
+ files:
73
+ - .gitignore
74
+ - .rspec
75
+ - Gemfile
76
+ - LICENSE.txt
77
+ - README.md
78
+ - Rakefile
79
+ - lib/random_attributes.rb
80
+ - lib/random_attributes/version.rb
81
+ - random_attributes.gemspec
82
+ - spec/random_attributes_spec.rb
83
+ - spec/spec_helper.rb
84
+ homepage: ""
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+
89
+ post_install_message:
90
+ rdoc_options: []
91
+
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - *id005
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - *id005
100
+ requirements: []
101
+
102
+ rubyforge_project:
103
+ rubygems_version: 2.0.3
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Data hash to object mapper
107
+ test_files:
108
+ - spec/random_attributes_spec.rb
109
+ - spec/spec_helper.rb