structure 0.26.0 → 0.27.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|