hal-interpretation 1.0.0 → 1.1.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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7dd0ca8e27a6128646364bb2d2fc57d341652703
|
4
|
+
data.tar.gz: fe9fd9ad161ad54e5cfaa096c95bd2a3ae2005c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb52b63015894a915d4cab0bf8636a935a2b499d51cff8d3eb9354a305bab97c209de37fe4ca385e822c7739cb23c3bfc1fda61846c719649d5f3c93ed4241b8
|
7
|
+
data.tar.gz: 0a21dcf648667768fc5ed137e7a9d64a5414778c08e474071a9f71fe7bc7acfc11f50b13703c2bebbcf7e4b7618ead28581d7e467931be345fe8650c84f9a426
|
@@ -11,12 +11,26 @@ module HalInterpretation
|
|
11
11
|
# document.
|
12
12
|
#
|
13
13
|
# attr_name - name of attribute on model to extract
|
14
|
+
#
|
14
15
|
# opts - hash of named arguments to method
|
15
|
-
#
|
16
|
-
#
|
16
|
+
#
|
17
|
+
# :from - JSON path from which to get the value for
|
18
|
+
# attribute. Default: "/#{attr_name}".
|
19
|
+
#
|
20
|
+
# :with - Callable that can extract the value when
|
21
|
+
# passed a HalClient::Representation of the item.
|
22
|
+
#
|
23
|
+
# :coercion - callable with which the raw value should be
|
24
|
+
# transformed before being stored.
|
17
25
|
def extract(attr_name, opts={})
|
18
|
-
|
19
|
-
|
26
|
+
extractor_opts = {
|
27
|
+
attr: attr_name,
|
28
|
+
location: opts.fetch(:from) { "/#{attr_name}" }
|
29
|
+
}
|
30
|
+
extractor_opts[:extraction_proc] = opts.fetch(:with) if opts.key? :with
|
31
|
+
extractor_opts[:coercion] = opts[:coercion] if opts.key? :coercion
|
32
|
+
|
33
|
+
extractors << Extractor.new(extractor_opts)
|
20
34
|
end
|
21
35
|
end
|
22
36
|
end
|
@@ -4,11 +4,22 @@ module HalInterpretation
|
|
4
4
|
class Extractor
|
5
5
|
# opts - named args
|
6
6
|
# :attr - name of attribute this object will extact.
|
7
|
+
#
|
7
8
|
# :location - JSON path from which to get the value.
|
8
|
-
|
9
|
+
#
|
10
|
+
# :extraction_proc - Callable that can extract the value when
|
11
|
+
# passed a HalClient::Representation of the item.
|
12
|
+
#
|
13
|
+
# :coercion - proc to pass the extracted value through before
|
14
|
+
# storing it.
|
15
|
+
def initialize(opts)
|
9
16
|
@attr = opts.fetch(:attr) { fail ArgumentError, "attr is required" }
|
10
17
|
@location = opts.fetch(:location) { "/#{attr}" }
|
11
|
-
@
|
18
|
+
@fetcher = opts.fetch(:extraction_proc) { Hana::Pointer.new(location).method(:eval) }
|
19
|
+
@value_coercion = opts.fetch(:coercion) { IDENTITY }
|
20
|
+
|
21
|
+
fail(ArgumentError, ":coercion must respond to #call") unless
|
22
|
+
value_coercion.respond_to? :call
|
12
23
|
end
|
13
24
|
|
14
25
|
# opts - named args
|
@@ -19,7 +30,8 @@ module HalInterpretation
|
|
19
30
|
def extract(opts)
|
20
31
|
from = opts.fetch(:from) { fail ArgumentError, "from is required" }
|
21
32
|
to = opts.fetch(:to) { fail ArgumentError, "to is required" }
|
22
|
-
|
33
|
+
|
34
|
+
to.send "#{attr}=", value_coercion.call(fetcher.call(from))
|
23
35
|
|
24
36
|
[]
|
25
37
|
rescue => err
|
@@ -29,6 +41,8 @@ module HalInterpretation
|
|
29
41
|
attr_reader :attr, :location
|
30
42
|
|
31
43
|
protected
|
32
|
-
attr_reader :
|
44
|
+
attr_reader :fetcher, :value_coercion
|
45
|
+
|
46
|
+
IDENTITY = ->(thing){ thing }
|
33
47
|
end
|
34
|
-
end
|
48
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
describe HalInterpretation::Extractor do
|
4
|
+
describe "creation" do
|
5
|
+
specify { expect{described_class.new(attr: "first_name", location: "/firstName")}
|
6
|
+
.not_to raise_error }
|
7
|
+
specify { expect{described_class.new(attr: "first_name", with: ->(hal_repr){ "bob" })}
|
8
|
+
.not_to raise_error }
|
9
|
+
specify { expect{described_class.new(attr: "first_name", location: "/firstName",
|
10
|
+
coercion: ->(){ 42 })}
|
11
|
+
.not_to raise_error }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "location based" do
|
15
|
+
subject(:extractor) { described_class.new(attr: "first_name", location: "/firstName") }
|
16
|
+
|
17
|
+
specify { expect{extractor.extract(from: source, to: target)}.not_to raise_error }
|
18
|
+
|
19
|
+
context "after extraction" do
|
20
|
+
before do extractor.extract(from: source, to: target) end
|
21
|
+
|
22
|
+
specify { expect(target.first_name).to eq "Alice" }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "lambda based" do
|
27
|
+
subject(:extractor) { described_class
|
28
|
+
.new(attr: "parent", location: "/_links/up",
|
29
|
+
extraction_proc: ->(hal_repr) {hal_repr.related_hrefs("up").first}) }
|
30
|
+
|
31
|
+
specify { expect{extractor.extract(from: source, to: target)}.not_to raise_error }
|
32
|
+
|
33
|
+
context "after extraction" do
|
34
|
+
before do extractor.extract(from: source, to: target) end
|
35
|
+
|
36
|
+
specify { expect(target.parent).to eq "http://foo" }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "coercion" do
|
41
|
+
subject(:extractor) { described_class.new(attr: "bday",
|
42
|
+
coercion: ->(val){ Time.parse(val) } ) }
|
43
|
+
before do extractor.extract(from: source, to: target) end
|
44
|
+
|
45
|
+
specify { expect(target.bday).to eq Time.utc(2013,10,10,12,13,14) }
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
let(:target) { Struct.new(:first_name, :bday, :parent).new }
|
50
|
+
let(:source) { HalClient::Representation.new(parsed_json: {
|
51
|
+
"firstName" => "Alice",
|
52
|
+
"bday" => "2013-10-10T12:13:14Z",
|
53
|
+
"_links" => {
|
54
|
+
"up" => { "href" => "http://foo" }}}) }
|
55
|
+
end
|
@@ -11,20 +11,28 @@ describe HalInterpretation do
|
|
11
11
|
item_class test_item_class
|
12
12
|
extract :name
|
13
13
|
extract :latitude, from: "/geo/latitude"
|
14
|
+
extract :up, with: ->(hal_repr){hal_repr.related_hrefs("up").first}, from: "/_links/up"
|
15
|
+
extract :bday, coercion: ->(val){ Time.parse(val) }
|
14
16
|
end }
|
15
17
|
|
16
18
|
context "valid single item" do
|
17
19
|
let(:json_doc) { <<-JSON }
|
18
20
|
{ "name": "foo"
|
21
|
+
,"bday": "2013-12-11T10:09:08Z"
|
19
22
|
,"geo": {
|
20
23
|
"latitude": 39.1
|
21
24
|
}
|
25
|
+
,"_links": {
|
26
|
+
"up": {"href": "/foo"}
|
27
|
+
}
|
22
28
|
}
|
23
29
|
JSON
|
24
30
|
|
25
31
|
specify { expect(interpreter.items).to have(1).item }
|
26
32
|
specify { expect(interpreter.items.first.name).to eq "foo" }
|
27
33
|
specify { expect(interpreter.items.first.latitude).to eq 39.1 }
|
34
|
+
specify { expect(interpreter.items.first.up).to eq "/foo" }
|
35
|
+
specify { expect(interpreter.items.first.bday).to eq Time.utc(2013,12,11,10,9,8) }
|
28
36
|
specify { expect(interpreter.problems).to be_empty }
|
29
37
|
end
|
30
38
|
|
@@ -32,14 +40,18 @@ describe HalInterpretation do
|
|
32
40
|
let(:json_doc) { <<-JSON }
|
33
41
|
{ "_embedded": {
|
34
42
|
"item": [{ "name": "foo"
|
43
|
+
,"bday": "2013-12-11T10:09:08Z"
|
35
44
|
,"geo": {
|
36
45
|
"latitude": 39.1
|
37
46
|
}
|
47
|
+
,"_links": { "up": {"href": "/foo"} }
|
38
48
|
}
|
39
49
|
,{ "name": "bar"
|
50
|
+
,"bday": "2013-12-11T10:09:08Z"
|
40
51
|
,"geo": {
|
41
52
|
"latitude": 39.2
|
42
53
|
}
|
54
|
+
,"_links": { "up": {"href": "/bar"} }
|
43
55
|
}]
|
44
56
|
}
|
45
57
|
}
|
@@ -62,6 +74,7 @@ describe HalInterpretation do
|
|
62
74
|
{ "geo": {
|
63
75
|
"latitude": "hello"
|
64
76
|
}
|
77
|
+
,"bday": "yesterday"
|
65
78
|
}
|
66
79
|
JSON
|
67
80
|
|
@@ -79,6 +92,8 @@ describe HalInterpretation do
|
|
79
92
|
.to include matching(%r(/name\b)).and(match(/\bblank\b/i)) }
|
80
93
|
specify { expect(interpreter.problems)
|
81
94
|
.to include matching(%r(/geo/latitude\b)).and(match(/\binvalid value\b/i)) }
|
95
|
+
specify { expect(interpreter.problems)
|
96
|
+
.to include matching(%r(/bday\b)).and(match(/\bno time\b/i)) }
|
82
97
|
end
|
83
98
|
|
84
99
|
context "collection w/ invalid attributes" do
|
@@ -126,7 +141,7 @@ describe HalInterpretation do
|
|
126
141
|
let(:test_item_class) { Class.new do
|
127
142
|
include ActiveModel::Validations
|
128
143
|
|
129
|
-
attr_accessor :name, :latitude
|
144
|
+
attr_accessor :name, :latitude, :up, :bday
|
130
145
|
|
131
146
|
def initialize
|
132
147
|
yield self
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hal-interpretation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hal-client
|
@@ -157,6 +157,7 @@ files:
|
|
157
157
|
- lib/hal_interpretation/extractor.rb
|
158
158
|
- lib/hal_interpretation/item_interpreter.rb
|
159
159
|
- lib/hal_interpretation/version.rb
|
160
|
+
- spec/hal_interpretation/extractor_spec.rb
|
160
161
|
- spec/hal_interpretation_spec.rb
|
161
162
|
- spec/spec_helper.rb
|
162
163
|
homepage: https://github.com/pezra/hal-interpretation
|
@@ -184,5 +185,6 @@ signing_key:
|
|
184
185
|
specification_version: 4
|
185
186
|
summary: Build models from HAL documents.
|
186
187
|
test_files:
|
188
|
+
- spec/hal_interpretation/extractor_spec.rb
|
187
189
|
- spec/hal_interpretation_spec.rb
|
188
190
|
- spec/spec_helper.rb
|