structure 0.26.0 → 0.27.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/LICENSE +1 -1
- data/README.md +27 -11
- metadata +11 -20
- data/.gitignore +0 -6
- data/Gemfile +0 -2
- data/Rakefile +0 -9
- data/lib/structure.rb +0 -49
- data/lib/structure/version.rb +0 -3
- data/structure.gemspec +0 -23
- data/test/structure_test.rb +0 -83
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 341847011b94385b6f9db184126c65b671aaea6a
|
4
|
+
data.tar.gz: 479f90296cf23777214e967acbe1f19529edb905
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39a77be13c27e5b73f3ef9e7e3dcf7c1ac51636b409de4f7dcd761f6bcaee6e8454f7c29742bb1f3707e7907924599a00843b70e9c0ecc77242927a40e7ea799
|
7
|
+
data.tar.gz: 488720d77236008080d9dedeba9cf31c57d17085a3f60a57c2f71c1309e1f7261c5386100fe746bfc038448ba3bc505bc04deec76abee99a486e0489c6581ffa
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,30 +1,46 @@
|
|
1
1
|
# Structure
|
2
2
|
|
3
|
-
|
3
|
+
Structure is minimal glue that helps you parse data—for instance, API responses—into immutable value objects.
|
4
4
|
|
5
5
|
## Usage
|
6
6
|
|
7
|
-
Mix in
|
7
|
+
Usage is straightforward. Mix in the module and define the parser methods with `.attribute`, a naming convention I decided to stick to.
|
8
8
|
|
9
9
|
```ruby
|
10
10
|
class Location
|
11
11
|
include Structure
|
12
12
|
|
13
|
-
|
13
|
+
def initialize(data)
|
14
|
+
@data = data
|
15
|
+
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
+
attribute :latitude do
|
18
|
+
parse(:latitude)
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
+
attribute :longitude do
|
22
|
+
parse(:longitude)
|
21
23
|
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
private
|
26
|
+
|
27
|
+
def parse(key)
|
28
|
+
# Heavy-duty parsing action on @data
|
25
29
|
end
|
26
30
|
end
|
31
|
+
```
|
27
32
|
|
28
|
-
|
29
|
-
|
33
|
+
Once you have your parser defined, initialise it with some data and take it to a drive.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
location = Location.new(data)
|
37
|
+
puts location.latitude # => Some latitude
|
38
|
+
puts location.to_h # => All attributes as a Ruby Hash
|
39
|
+
puts location # => Bonus: This will pretty-inspect the instance
|
40
|
+
```
|
41
|
+
|
42
|
+
When testing objects the parser collaborates in, you may benefit from a double to stand in for the real parser.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
double = Location.to_struct.new(location: 10, latitude: 10)
|
30
46
|
```
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: structure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.27.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hakan Ensari
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -38,25 +38,16 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
description:
|
42
|
-
email:
|
43
|
-
- hakan.ensari@papercavalier.com
|
41
|
+
description:
|
42
|
+
email:
|
44
43
|
executables: []
|
45
44
|
extensions: []
|
46
45
|
extra_rdoc_files: []
|
47
46
|
files:
|
48
|
-
- ".gitignore"
|
49
|
-
- Gemfile
|
50
47
|
- LICENSE
|
51
48
|
- README.md
|
52
|
-
|
53
|
-
|
54
|
-
- lib/structure/version.rb
|
55
|
-
- structure.gemspec
|
56
|
-
- test/structure_test.rb
|
57
|
-
homepage: http://github.com/hakanensari/structure
|
58
|
-
licenses:
|
59
|
-
- MIT
|
49
|
+
homepage:
|
50
|
+
licenses: []
|
60
51
|
metadata: {}
|
61
52
|
post_install_message:
|
62
53
|
rdoc_options: []
|
@@ -66,7 +57,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
57
|
requirements:
|
67
58
|
- - ">="
|
68
59
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
60
|
+
version: '2.1'
|
70
61
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
62
|
requirements:
|
72
63
|
- - ">="
|
@@ -74,9 +65,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
65
|
version: '0'
|
75
66
|
requirements: []
|
76
67
|
rubyforge_project:
|
77
|
-
rubygems_version: 2.2.
|
68
|
+
rubygems_version: 2.2.2
|
78
69
|
signing_key:
|
79
70
|
specification_version: 4
|
80
|
-
summary:
|
81
|
-
test_files:
|
82
|
-
|
71
|
+
summary: Parses data into value objects
|
72
|
+
test_files: []
|
73
|
+
has_rdoc:
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
data/lib/structure.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
module Structure
|
2
|
-
def self.included(base)
|
3
|
-
base.extend(ClassMethods)
|
4
|
-
base.instance_variable_set(:@value_names, [])
|
5
|
-
end
|
6
|
-
|
7
|
-
def values
|
8
|
-
vals = {}
|
9
|
-
self.class.value_names.each { |name| vals[name] = self.send(name) }
|
10
|
-
|
11
|
-
vals
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_h
|
15
|
-
Hash[values.dup.map { |k, v| [k, v.respond_to?(:to_h) ? v.to_h : v] } ]
|
16
|
-
end
|
17
|
-
|
18
|
-
def ==(other)
|
19
|
-
values == other.values
|
20
|
-
end
|
21
|
-
alias :eql? :==
|
22
|
-
|
23
|
-
def inspect
|
24
|
-
str = "#<#{self.class}"
|
25
|
-
|
26
|
-
first = true
|
27
|
-
values.each do |k, v|
|
28
|
-
str << ',' unless first
|
29
|
-
first = false
|
30
|
-
str << " #{k}=#{v.inspect}"
|
31
|
-
end
|
32
|
-
|
33
|
-
str << '>'
|
34
|
-
end
|
35
|
-
alias :to_s :inspect
|
36
|
-
|
37
|
-
module ClassMethods
|
38
|
-
attr :value_names
|
39
|
-
|
40
|
-
def inherited(subclass)
|
41
|
-
subclass.instance_variable_set(:@value_names, value_names.dup)
|
42
|
-
end
|
43
|
-
|
44
|
-
def value(name, &blk)
|
45
|
-
define_method(name, &blk)
|
46
|
-
@value_names << name
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/lib/structure/version.rb
DELETED
data/structure.gemspec
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'structure/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = 'structure'
|
8
|
-
spec.version = Structure::VERSION
|
9
|
-
spec.authors = ['Hakan Ensari']
|
10
|
-
spec.email = ['hakan.ensari@papercavalier.com']
|
11
|
-
spec.description = 'Value objects in Ruby'
|
12
|
-
spec.summary = 'Value objects in Ruby'
|
13
|
-
spec.homepage = 'http://github.com/hakanensari/structure'
|
14
|
-
spec.license = 'MIT'
|
15
|
-
|
16
|
-
spec.files = `git ls-files`.split("\n")
|
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_development_dependency 'minitest'
|
22
|
-
spec.add_development_dependency 'rake'
|
23
|
-
end
|
data/test/structure_test.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'structure'
|
3
|
-
|
4
|
-
class Location
|
5
|
-
include Structure
|
6
|
-
|
7
|
-
attr :res
|
8
|
-
|
9
|
-
def initialize(res)
|
10
|
-
@res = res
|
11
|
-
end
|
12
|
-
|
13
|
-
value :latitude do
|
14
|
-
res.fetch(:lat)
|
15
|
-
end
|
16
|
-
|
17
|
-
value :longitude do
|
18
|
-
res.fetch(:lng)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class StructureTest < MiniTest::Test
|
23
|
-
def setup
|
24
|
-
@location = Location.new(lat: 10, lng: 100)
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_has_value
|
28
|
-
assert_equal 10, @location.latitude
|
29
|
-
assert_equal 100, @location.longitude
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_class_returns_value_names
|
33
|
-
assert_equal [:latitude, :longitude], Location.value_names
|
34
|
-
end
|
35
|
-
|
36
|
-
def test_returns_values
|
37
|
-
assert_equal({ latitude: 10, longitude: 100 }, @location.values)
|
38
|
-
assert_equal @location.to_h, @location.values
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_compares
|
42
|
-
@other = Location.new(lng: 100, lat: 10)
|
43
|
-
assert @location == @other
|
44
|
-
assert @location.eql?(@other)
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_pretty_inspects
|
48
|
-
assert_equal '#<Location latitude=10, longitude=100>', @location.inspect
|
49
|
-
assert_equal @location.to_s, @location.inspect
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_subclasses
|
53
|
-
subclass = Class.new(Location) do
|
54
|
-
value(:name) { 'foo' }
|
55
|
-
end
|
56
|
-
obj = subclass.new(lat: 10, lng: 100)
|
57
|
-
|
58
|
-
assert_equal({ latitude: 10, longitude: 100, name: 'foo' }, obj.values)
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_recursively_casts_to_hash
|
62
|
-
city_class = Class.new do
|
63
|
-
include Structure
|
64
|
-
|
65
|
-
attr :res
|
66
|
-
|
67
|
-
def initialize(res)
|
68
|
-
@res = res
|
69
|
-
end
|
70
|
-
|
71
|
-
value :name do
|
72
|
-
res.fetch(:name)
|
73
|
-
end
|
74
|
-
|
75
|
-
value :location do
|
76
|
-
Location.new(res.fetch(:loc))
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
city = city_class.new(name: 'London', loc: { lat: 51.5, lng: 0.1 })
|
81
|
-
assert_equal({ name: 'London', location: { latitude: 51.5, longitude: 0.1 }}, city.to_h)
|
82
|
-
end
|
83
|
-
end
|