lazy_doc 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +3 -3
- data/lib/lazy_doc.rb +1 -0
- data/lib/lazy_doc/attribute_not_found_error.rb +1 -1
- data/lib/lazy_doc/camelizable_string.rb +15 -0
- data/lib/lazy_doc/commands.rb +18 -0
- data/lib/lazy_doc/commands/as_class_command.rb +10 -1
- data/lib/lazy_doc/commands/via_command.rb +18 -5
- data/lib/lazy_doc/dsl.rb +4 -7
- data/lib/lazy_doc/version.rb +1 -1
- data/spec/acceptance/basic_behavior_spec.rb +22 -3
- data/spec/acceptance/support/user.json +6 -1
- data/spec/lib/lazy_doc/camelizable_string_spec.rb +21 -0
- data/spec/lib/lazy_doc/commands/as_class_command_spec.rb +15 -2
- data/spec/lib/lazy_doc/commands/via_command_spec.rb +9 -0
- data/spec/lib/lazy_doc/commands_spec.rb +48 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OGMxMGUwZTdmMDk4OGUyZGRhMTliNTI3NmUzM2RjZDMwYjY0ODM3Yg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MTNhYWFlY2MzOTQ0YWFmNDYyZTMxZTBkMDI0Mjk3YmVjMjg2YWFkZg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTJjMjgwZmYyZTA5ZWIxNWFmODBiMWUwZGNjZTM3ZGNiMDFlYzRhOTI4ZmE2
|
10
|
+
MjFiZWFhZWI2YmI5YzZmOTlmNWMwNmQwODg2M2MxNDgzYzM1ODBkYjJhZDlm
|
11
|
+
MTNmMjkzMGIyNWY5MzY3MTgzYWI1YmZkZDc2ZDMzZmQwMWMxODQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZTQ0MWIxMjJmMzJiNmFlMjcxNTg1MTIxMDEyYjNkNjc5MDI5NDE0YzIxMTcx
|
14
|
+
MDJkMzM5NmIzOTIxOWQ4ZjNmNzY2NmM0ODJkZWJiYzc3NDEyMGMyMzFjYWRk
|
15
|
+
OGExNjc5MmIxMTU3MjQ4MzdkOTFlOTQ3ZjE4ODE0M2UxNzc5ODY=
|
data/README.md
CHANGED
@@ -66,13 +66,13 @@ puts user.job
|
|
66
66
|
5. DONE - Objects from sub-trees. ex: `access :profile, as: Profile` (This would construct a LazyDoc Profile object and pass the json found at "profile" to it)
|
67
67
|
6. Collections.
|
68
68
|
- DONE - Map. For example, extract array of customer names from array of customers. ex: `access :customers, extract: :name`
|
69
|
-
- Objects from collection. Instead of extracting just the name, extract whole objects like in #5. ex: `access :customers, as: Customer`
|
70
|
-
- Other Collection manipulations, select, inject, etc
|
69
|
+
- DONE - Objects from collection. Instead of extracting just the name, extract whole objects like in #5. ex: `access :customers, as: Customer`
|
70
|
+
- Other Collection manipulations, select, inject, count, etc
|
71
71
|
7. Joins
|
72
72
|
- Using previously defined attributes. ex: `join :address, from: [:street, :city, :state:, :zip]`
|
73
73
|
- Defining attributes in place.
|
74
74
|
8. DONE - Multiple simple paths in one line (ex: `access :name, :street, :city, :state`)
|
75
|
-
9. Infer camelCase to snake_case and vice versa in JSON ex: `access :customer_name` (Where the json has customerName)
|
75
|
+
9. DONE- Infer camelCase to snake_case and vice versa in JSON ex: `access :customer_name` (Where the json has customerName)
|
76
76
|
10. XML support
|
77
77
|
|
78
78
|
## Contributing
|
data/lib/lazy_doc.rb
CHANGED
data/lib/lazy_doc/commands.rb
CHANGED
@@ -8,3 +8,21 @@ require 'lazy_doc/commands/default_value_command'
|
|
8
8
|
require 'lazy_doc/commands/extract_command'
|
9
9
|
require 'lazy_doc/commands/finally_command'
|
10
10
|
require 'lazy_doc/commands/via_command'
|
11
|
+
|
12
|
+
module LazyDoc::Commands
|
13
|
+
OPTIONAL_COMMAND_CLASSES = {
|
14
|
+
default: DefaultValueCommand,
|
15
|
+
as: AsClassCommand,
|
16
|
+
extract: ExtractCommand,
|
17
|
+
finally: FinallyCommand
|
18
|
+
}
|
19
|
+
|
20
|
+
def self.create_commands_for(options)
|
21
|
+
options.map do |key, initialization_value|
|
22
|
+
if OPTIONAL_COMMAND_CLASSES.has_key?(key)
|
23
|
+
OPTIONAL_COMMAND_CLASSES[key].new(initialization_value)
|
24
|
+
end
|
25
|
+
end.compact
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -7,7 +7,16 @@ module LazyDoc::Commands
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def execute(value)
|
10
|
-
klass.nil?
|
10
|
+
if klass.nil?
|
11
|
+
value
|
12
|
+
else
|
13
|
+
if value.is_a? Array
|
14
|
+
value.map { |element| klass.new(element.to_json) }
|
15
|
+
else
|
16
|
+
klass.new(value.to_json)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
11
20
|
end
|
12
21
|
end
|
13
22
|
end
|
@@ -7,15 +7,28 @@ module LazyDoc::Commands
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def execute(document)
|
10
|
-
path.inject(document) do |
|
11
|
-
|
12
|
-
raise LazyDoc::AttributeNotFoundError.new("Unable to access #{attribute} via #{path.join(', ')}")
|
13
|
-
end
|
10
|
+
path.inject(document) do |sub_document, attribute|
|
11
|
+
attribute_identifier = determine_attribute_identifier(attribute, sub_document)
|
14
12
|
|
15
|
-
|
13
|
+
sub_document[attribute_identifier]
|
16
14
|
end
|
17
15
|
end
|
18
16
|
|
17
|
+
private
|
18
|
+
|
19
|
+
def determine_attribute_identifier(attribute, sub_document)
|
20
|
+
camelizable_attribute = LazyDoc::CamelizableString.new(attribute.to_s)
|
21
|
+
|
22
|
+
if sub_document.has_key?(camelizable_attribute.original)
|
23
|
+
camelizable_attribute.original
|
24
|
+
elsif sub_document.has_key?(camelizable_attribute.camelize)
|
25
|
+
camelizable_attribute.camelize
|
26
|
+
else
|
27
|
+
raise LazyDoc::AttributeNotFoundError.new("Unable to access #{attribute} via #{path.join(', ')}")
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
19
32
|
end
|
20
33
|
|
21
34
|
end
|
data/lib/lazy_doc/dsl.rb
CHANGED
@@ -33,11 +33,8 @@ module LazyDoc
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def define_access_method_for(attribute, options)
|
36
|
-
|
37
|
-
|
38
|
-
Commands::AsClassCommand.new(options[:as]),
|
39
|
-
Commands::ExtractCommand.new(options[:extract]),
|
40
|
-
Commands::FinallyCommand.new(options[:finally]))
|
36
|
+
optional_commands = Commands.create_commands_for options
|
37
|
+
create_method(attribute, Commands::ViaCommand.new(options[:via] || attribute), optional_commands)
|
41
38
|
end
|
42
39
|
|
43
40
|
def define_access_methods_for(attributes)
|
@@ -47,10 +44,10 @@ module LazyDoc
|
|
47
44
|
|
48
45
|
end
|
49
46
|
|
50
|
-
def create_method(attribute,
|
47
|
+
def create_method(attribute, via_command, optional_commands = [])
|
51
48
|
define_method attribute do
|
52
49
|
memoizer.memoize attribute do
|
53
|
-
value =
|
50
|
+
value = via_command.execute(embedded_doc)
|
54
51
|
|
55
52
|
optional_commands.inject(value) do |final_value, command|
|
56
53
|
final_value = command.execute(final_value)
|
data/lib/lazy_doc/version.rb
CHANGED
@@ -4,7 +4,7 @@ describe 'basic behavior with a simple JSON document' do
|
|
4
4
|
class Friends
|
5
5
|
include LazyDoc::DSL
|
6
6
|
|
7
|
-
access :best_friend
|
7
|
+
access :best_friend
|
8
8
|
access :lover
|
9
9
|
|
10
10
|
def initialize(json)
|
@@ -12,18 +12,29 @@ describe 'basic behavior with a simple JSON document' do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
class Accomplishment
|
16
|
+
include LazyDoc::DSL
|
17
|
+
|
18
|
+
access :description
|
19
|
+
|
20
|
+
def initialize(json)
|
21
|
+
lazily_embed(json)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
15
25
|
class User
|
16
26
|
include LazyDoc::DSL
|
17
27
|
|
18
28
|
access :name
|
19
29
|
access :phone, :zip
|
20
30
|
access :home_town
|
21
|
-
access :
|
31
|
+
access :street_address
|
22
32
|
access :job_title, via: [:profile, :occupation, :title]
|
23
33
|
access :born_on, via: [:profile, :bornOn], finally: lambda { |born_on| born_on.to_i }
|
24
34
|
access :friends, as: Friends
|
25
35
|
access :father, default: 'Chuck Palahniuk'
|
26
36
|
access :fight_club_rules, via: [:fightClub, :rules], extract: :title
|
37
|
+
access :accomplishments, as: Accomplishment
|
27
38
|
|
28
39
|
def initialize(json)
|
29
40
|
lazily_embed(json)
|
@@ -38,7 +49,7 @@ describe 'basic behavior with a simple JSON document' do
|
|
38
49
|
its(:name) { should == 'Tyler Durden' }
|
39
50
|
its(:phone) { should == '288-555-0153' }
|
40
51
|
its(:zip) { should == '00000' }
|
41
|
-
its(:
|
52
|
+
its(:street_address) { should == 'Paper Street' }
|
42
53
|
its(:job_title) { should == 'Soap Maker' }
|
43
54
|
its(:born_on) { should == 1999 }
|
44
55
|
specify { expect { user.home_town }.to raise_error(LazyDoc::AttributeNotFoundError) }
|
@@ -54,4 +65,12 @@ describe 'basic behavior with a simple JSON document' do
|
|
54
65
|
its(:fight_club_rules) { should == ['You do not talk about Fight Club',
|
55
66
|
'You DO NOT talk about Fight Club',
|
56
67
|
'If someone says stop or goes limp, taps out the fight is over'] }
|
68
|
+
|
69
|
+
context 'accomplishments' do
|
70
|
+
let(:accomplishments) { user.accomplishments }
|
71
|
+
|
72
|
+
specify { expect(accomplishments[0].description).to eq('Sold a lot of soap') }
|
73
|
+
specify { expect(accomplishments[1].description).to eq('Started fight club with himself') }
|
74
|
+
specify { expect(accomplishments[2].description).to eq('Blew up a bunch of credit card companies') }
|
75
|
+
end
|
57
76
|
end
|
@@ -21,5 +21,10 @@
|
|
21
21
|
{"number": 2, "title": "You DO NOT talk about Fight Club"},
|
22
22
|
{"number": 3, "title": "If someone says stop or goes limp, taps out the fight is over"}
|
23
23
|
]
|
24
|
-
}
|
24
|
+
},
|
25
|
+
"accomplishments": [
|
26
|
+
{"description": "Sold a lot of soap"},
|
27
|
+
{"description": "Started fight club with himself"},
|
28
|
+
{"description": "Blew up a bunch of credit card companies"}
|
29
|
+
]
|
25
30
|
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
module LazyDoc
|
4
|
+
describe CamelizableString do
|
5
|
+
describe '#camelize' do
|
6
|
+
it 'converts a string from snake_case to camelCase' do
|
7
|
+
camelized_string = CamelizableString.new('snake_case').camelize
|
8
|
+
|
9
|
+
expect(camelized_string).to eq('snakeCase')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'has no effect on a string with no underscores' do
|
13
|
+
camelized_string = CamelizableString.new('snakecase').camelize
|
14
|
+
|
15
|
+
expect(camelized_string).to eq('snakecase')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -3,8 +3,7 @@ require_relative '../../../spec_helper'
|
|
3
3
|
module LazyDoc
|
4
4
|
describe Commands::AsClassCommand do
|
5
5
|
class Foo
|
6
|
-
def initialize(value)
|
7
|
-
end
|
6
|
+
def initialize(value) end
|
8
7
|
end
|
9
8
|
|
10
9
|
let(:value) { {foo: 'bar'} }
|
@@ -38,5 +37,19 @@ module LazyDoc
|
|
38
37
|
|
39
38
|
as_class_command.execute(value)
|
40
39
|
end
|
40
|
+
|
41
|
+
context 'when the value being sent to the AsClassCommand is an array' do
|
42
|
+
let(:value) { [{foo: 'bar'}, {foo: 'baz'}] }
|
43
|
+
|
44
|
+
it 'returns an array of objects of the specified class' do
|
45
|
+
as_class_command = Commands::AsClassCommand.new(Foo)
|
46
|
+
|
47
|
+
as_class_value = as_class_command.execute(value)
|
48
|
+
|
49
|
+
expect(as_class_value).to be_an Array
|
50
|
+
expect(as_class_value[0]).to be_a Foo
|
51
|
+
expect(as_class_value[1]).to be_a Foo
|
52
|
+
end
|
53
|
+
end
|
41
54
|
end
|
42
55
|
end
|
@@ -32,5 +32,14 @@ module LazyDoc
|
|
32
32
|
|
33
33
|
expect { via.execute(document) }.to raise_error(AttributeNotFoundError)
|
34
34
|
end
|
35
|
+
|
36
|
+
it 'finds the attribute when specified as snake_case but is found in camelCase' do
|
37
|
+
document = {'helloWorld' => 'foobar'}
|
38
|
+
via = Commands::ViaCommand.new(:hello_world)
|
39
|
+
|
40
|
+
final_value = via.execute(document)
|
41
|
+
|
42
|
+
expect(final_value).to eq('foobar')
|
43
|
+
end
|
35
44
|
end
|
36
45
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
module LazyDoc
|
4
|
+
describe Commands do
|
5
|
+
describe '#create_commands_for' do
|
6
|
+
class FooCommand
|
7
|
+
def initialize(_) end
|
8
|
+
end
|
9
|
+
class BarCommand
|
10
|
+
def initialize(_) end
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:all) do
|
14
|
+
@optional_command_classes = Commands::OPTIONAL_COMMAND_CLASSES.dup
|
15
|
+
Commands::OPTIONAL_COMMAND_CLASSES = {foo: FooCommand, bar: BarCommand}
|
16
|
+
end
|
17
|
+
|
18
|
+
after(:all) do
|
19
|
+
Commands::OPTIONAL_COMMAND_CLASSES = @optional_command_classes
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:initialization_value) { 'initialization value' }
|
23
|
+
|
24
|
+
it 'creates a command object for the specified option' do
|
25
|
+
options = {foo: initialization_value}
|
26
|
+
commands = Commands.create_commands_for(options)
|
27
|
+
|
28
|
+
expect(commands[0]).to be_a FooCommand
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'creates a command object for multiple options' do
|
32
|
+
options = {foo: initialization_value, bar: initialization_value}
|
33
|
+
commands = Commands.create_commands_for(options)
|
34
|
+
|
35
|
+
expect(commands[0]).to be_a FooCommand
|
36
|
+
expect(commands[1]).to be_a BarCommand
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'ignores options for which it does not have a matching command' do
|
40
|
+
options = {unknown: initialization_value}
|
41
|
+
commands = Commands.create_commands_for(options)
|
42
|
+
|
43
|
+
expect(commands).to be_empty
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lazy_doc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Oglesby
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- lazy_doc.gemspec
|
59
59
|
- lib/lazy_doc.rb
|
60
60
|
- lib/lazy_doc/attribute_not_found_error.rb
|
61
|
+
- lib/lazy_doc/camelizable_string.rb
|
61
62
|
- lib/lazy_doc/commands.rb
|
62
63
|
- lib/lazy_doc/commands/as_class_command.rb
|
63
64
|
- lib/lazy_doc/commands/default_value_command.rb
|
@@ -69,11 +70,13 @@ files:
|
|
69
70
|
- lib/lazy_doc/version.rb
|
70
71
|
- spec/acceptance/basic_behavior_spec.rb
|
71
72
|
- spec/acceptance/support/user.json
|
73
|
+
- spec/lib/lazy_doc/camelizable_string_spec.rb
|
72
74
|
- spec/lib/lazy_doc/commands/as_class_command_spec.rb
|
73
75
|
- spec/lib/lazy_doc/commands/default_value_command_spec.rb
|
74
76
|
- spec/lib/lazy_doc/commands/extract_command_spec.rb
|
75
77
|
- spec/lib/lazy_doc/commands/finally_command_spec.rb
|
76
78
|
- spec/lib/lazy_doc/commands/via_command_spec.rb
|
79
|
+
- spec/lib/lazy_doc/commands_spec.rb
|
77
80
|
- spec/lib/lazy_doc/dsl_spec.rb
|
78
81
|
- spec/lib/lazy_doc/memoizer_spec.rb
|
79
82
|
- spec/spec_helper.rb
|
@@ -105,11 +108,13 @@ summary: An implementation of the Embedded Document pattern for POROs
|
|
105
108
|
test_files:
|
106
109
|
- spec/acceptance/basic_behavior_spec.rb
|
107
110
|
- spec/acceptance/support/user.json
|
111
|
+
- spec/lib/lazy_doc/camelizable_string_spec.rb
|
108
112
|
- spec/lib/lazy_doc/commands/as_class_command_spec.rb
|
109
113
|
- spec/lib/lazy_doc/commands/default_value_command_spec.rb
|
110
114
|
- spec/lib/lazy_doc/commands/extract_command_spec.rb
|
111
115
|
- spec/lib/lazy_doc/commands/finally_command_spec.rb
|
112
116
|
- spec/lib/lazy_doc/commands/via_command_spec.rb
|
117
|
+
- spec/lib/lazy_doc/commands_spec.rb
|
113
118
|
- spec/lib/lazy_doc/dsl_spec.rb
|
114
119
|
- spec/lib/lazy_doc/memoizer_spec.rb
|
115
120
|
- spec/spec_helper.rb
|