render 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Gemfile +1 -1
- data/lib/render.rb +12 -50
- data/lib/render/{array_attribute.rb → attributes/array_attribute.rb} +3 -4
- data/lib/render/attributes/attribute.rb +48 -0
- data/lib/render/{hash_attribute.rb → attributes/hash_attribute.rb} +2 -4
- data/lib/render/definition.rb +31 -0
- data/lib/render/extensions/dottable_hash.rb +82 -0
- data/lib/render/extensions/symbolizable_array.rb +26 -0
- data/lib/render/extensions/symbolizable_hash.rb +28 -0
- data/lib/render/generator.rb +58 -4
- data/lib/render/graph.rb +29 -34
- data/lib/render/schema.rb +12 -12
- data/lib/render/type.rb +63 -0
- data/lib/render/version.rb +1 -1
- data/rakefile.rb +3 -3
- data/readme.md +17 -38
- data/render.gemspec +5 -7
- data/spec/functional/{representation → render}/attribute_spec.rb +3 -4
- data/spec/functional/{representation → render}/graph_spec.rb +6 -6
- data/spec/functional/{representation → render}/nested_schemas_spec.rb +0 -0
- data/spec/functional/{representation → render}/schema_spec.rb +0 -0
- data/spec/integration/render/graph_spec.rb +119 -0
- data/spec/integration/render/nested_graph_spec.rb +67 -0
- data/spec/integration/render/schema_spec.rb +90 -0
- data/spec/support/helpers.rb +2 -1
- data/spec/{schemas → support/schemas}/film.json +1 -0
- data/spec/{schemas → support/schemas}/films.json +1 -0
- data/spec/unit/gemspec_spec.rb +8 -0
- data/spec/unit/{array_attribute_spec.rb → render/attributes/array_attribute_spec.rb} +1 -1
- data/spec/unit/render/{attribute_spec.rb → attributes/attribute_spec.rb} +0 -0
- data/spec/unit/render/{hash_attribute_spec.rb → attributes/hash_attribute_spec.rb} +3 -1
- data/spec/unit/render/definition_spec.rb +85 -0
- data/spec/unit/render/extensions/dottable_hash_spec.rb +148 -0
- data/spec/unit/render/extensions/symbolizable_array_spec.rb +20 -0
- data/spec/unit/render/generator_spec.rb +44 -22
- data/spec/unit/render/graph_spec.rb +18 -18
- data/spec/unit/render/schema_spec.rb +11 -16
- data/spec/unit/render/type_spec.rb +83 -0
- data/spec/unit/render_spec.rb +0 -139
- metadata +70 -60
- data/lib/extensions/boolean.rb +0 -2
- data/lib/extensions/enumerable.rb +0 -16
- data/lib/extensions/hash.rb +0 -39
- data/lib/render/attribute.rb +0 -59
- data/lib/render/dottable_hash.rb +0 -113
- data/spec/integration/nested_graph_spec.rb +0 -85
- data/spec/integration/single_graph_spec.rb +0 -76
- data/spec/unit/extensions/boolean_spec.rb +0 -7
- data/spec/unit/render/dottable_hash_spec.rb +0 -231
@@ -1,85 +0,0 @@
|
|
1
|
-
require "render"
|
2
|
-
|
3
|
-
describe Render do
|
4
|
-
before(:all) do
|
5
|
-
Render.load_definitions!(Helpers::SCHEMA_DIRECTORY)
|
6
|
-
end
|
7
|
-
|
8
|
-
after(:all) do
|
9
|
-
Render.definitions = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
describe "request" do
|
13
|
-
before(:each) do
|
14
|
-
@films_endpoint = "http://films.local/films"
|
15
|
-
@film_endpoint = "http://films.local/films/:id"
|
16
|
-
@aquatic_id = UUID.generate
|
17
|
-
@darjeeling_id = UUID.generate
|
18
|
-
@aquatic_name = "The Life Aquatic with Steve Zissou"
|
19
|
-
@darjeeling_name = "The Darjeeling Limited"
|
20
|
-
end
|
21
|
-
|
22
|
-
it "returns structured data for nested queries" do
|
23
|
-
films_index_response = [{ id: @aquatic_id }, { id: @darjeeling_id }]
|
24
|
-
stub_request(:get, @films_endpoint).to_return({ body: films_index_response.to_json })
|
25
|
-
|
26
|
-
aquatic_name = "The Life Aquatic with Steve Zissou"
|
27
|
-
aquatic_uri = @film_endpoint.gsub(":id", @aquatic_id)
|
28
|
-
stub_request(:get, aquatic_uri).to_return({ body: { name: aquatic_name }.to_json })
|
29
|
-
|
30
|
-
darjeeling_name = "The Darjeeling Limited"
|
31
|
-
darjeeling_uri = @film_endpoint.gsub(":id", @darjeeling_id)
|
32
|
-
stub_request(:get, darjeeling_uri).to_return({ body: { name: darjeeling_name }.to_json })
|
33
|
-
|
34
|
-
options = {
|
35
|
-
graphs: [Render::Graph.new(:films_show, { endpoint: @film_endpoint, relationships: { id: :id }})],
|
36
|
-
endpoint: @films_endpoint
|
37
|
-
}
|
38
|
-
graph = Render::Graph.new(:films_index, options)
|
39
|
-
graph.render.should == {
|
40
|
-
films_index: {
|
41
|
-
films: films_index_response
|
42
|
-
},
|
43
|
-
films_show: [
|
44
|
-
{ film: { name: aquatic_name, year: nil } },
|
45
|
-
{ film: { name: darjeeling_name, year: nil } }
|
46
|
-
]
|
47
|
-
}
|
48
|
-
graph.rendered_data.films_show.first.film.name.should == aquatic_name
|
49
|
-
end
|
50
|
-
|
51
|
-
it "makes subsequent calls from archetype array data" do
|
52
|
-
stub_request(:get, @films_endpoint).to_return({ body: [@aquatic_id, @darjeeling_id].to_json })
|
53
|
-
|
54
|
-
aquatic = @film_endpoint.gsub(":id", @aquatic_id)
|
55
|
-
stub_request(:get, aquatic).to_return({ body: { name: @aquatic_name }.to_json })
|
56
|
-
|
57
|
-
darjeeling = @film_endpoint.gsub(":id", @darjeeling_id)
|
58
|
-
stub_request(:get, darjeeling).to_return({ body: { name: @darjeeling_name }.to_json })
|
59
|
-
|
60
|
-
films = Render::Schema.new({
|
61
|
-
title: :films,
|
62
|
-
type: Array,
|
63
|
-
items: {
|
64
|
-
type: UUID
|
65
|
-
}
|
66
|
-
})
|
67
|
-
|
68
|
-
film = Render::Schema.new({
|
69
|
-
title: :film,
|
70
|
-
type: Object,
|
71
|
-
properties: {
|
72
|
-
name: { type: String }
|
73
|
-
}
|
74
|
-
})
|
75
|
-
|
76
|
-
films = Render::Graph.new(films, { endpoint: @films_endpoint })
|
77
|
-
films.graphs << Render::Graph.new(film, { endpoint: @film_endpoint, relationships: { id: :id } })
|
78
|
-
films.render.film.should =~ [
|
79
|
-
{ name: @aquatic_name },
|
80
|
-
{ name: @darjeeling_name }
|
81
|
-
]
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
require "render"
|
2
|
-
|
3
|
-
describe Render do
|
4
|
-
before(:all) do
|
5
|
-
Render.load_definitions!(Helpers::SCHEMA_DIRECTORY)
|
6
|
-
end
|
7
|
-
|
8
|
-
after(:all) do
|
9
|
-
Render.definitions = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
before(:each) do
|
13
|
-
@film_id = UUID.generate
|
14
|
-
@film_name = "The Life Aqautic with Steve Zissou"
|
15
|
-
|
16
|
-
# Typically in environmental config
|
17
|
-
@secret_code = "3892n-2-n2iu1bf1cSdas0dDSAF"
|
18
|
-
@films_endpoint = "http://films.local/films?:secret_code"
|
19
|
-
@film_endpoint = "http://films.local/films/:id?:secret_code"
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "requests" do
|
23
|
-
it "returns structured data" do
|
24
|
-
aquatic_uri = @films_endpoint.gsub(":secret_code", "secret_code=#{@secret_code}")
|
25
|
-
stub_request(:get, aquatic_uri).to_return({ body: [{ id: @film_id }].to_json })
|
26
|
-
|
27
|
-
graph = Render::Graph.new(:films_index, { endpoint: @films_endpoint, secret_code: @secret_code })
|
28
|
-
graph.render.should == { films_index: { films: [{ id: @film_id }] } }
|
29
|
-
end
|
30
|
-
|
31
|
-
it "returns structured data for specific resources" do
|
32
|
-
id = UUID.generate
|
33
|
-
aquatic_uri = @film_endpoint.gsub(":id", id).gsub(":secret_code", "secret_code=#{@secret_code}")
|
34
|
-
stub_request(:get, aquatic_uri).to_return({ body: { name: @film_name }.to_json })
|
35
|
-
|
36
|
-
graph = Render::Graph.new(:films_show, { id: id, endpoint: @film_endpoint, secret_code: @secret_code })
|
37
|
-
graph.render.should == { films_show: { film: { name: @film_name, year: nil } } }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe "stubbed responses" do
|
42
|
-
before(:each) do
|
43
|
-
Render.stub({ live: false })
|
44
|
-
end
|
45
|
-
|
46
|
-
it "use meaningful values" do
|
47
|
-
response = Render::Graph.new(:films_show).render({ name: @film_name })
|
48
|
-
|
49
|
-
stub_request(:post, "http://films.local/create").to_return({ body: response.to_json })
|
50
|
-
response = post_film(:anything)["films_show"]["film"]
|
51
|
-
|
52
|
-
response["name"].should be_a(String)
|
53
|
-
response["year"].should be_a(Integer)
|
54
|
-
end
|
55
|
-
|
56
|
-
it "allows users to specify specific values" do
|
57
|
-
response = Render::Schema.new(:films_show).render!({ name: @film_name })
|
58
|
-
|
59
|
-
data = { name: @film_name }.to_json
|
60
|
-
request = stub_request(:post, "http://films.local/create").with({ body: data }).to_return({ body: response.to_json })
|
61
|
-
|
62
|
-
response = post_film(data)["films_show"]["film"]
|
63
|
-
request.should have_been_made
|
64
|
-
response["name"].should == @film_name
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def post_film(data)
|
69
|
-
response = Net::HTTP.start("films.local", 80) do |http|
|
70
|
-
request = Net::HTTP::Post.new("/create")
|
71
|
-
request.body = data
|
72
|
-
http.request(request)
|
73
|
-
end
|
74
|
-
JSON.parse(response.body)
|
75
|
-
end
|
76
|
-
end
|
@@ -1,231 +0,0 @@
|
|
1
|
-
require "render/dottable_hash"
|
2
|
-
|
3
|
-
module Render
|
4
|
-
describe DottableHash do
|
5
|
-
before(:each) do
|
6
|
-
@dottable_hash = DottableHash.new
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "new" do
|
10
|
-
it "creates from a hash" do
|
11
|
-
dottable_hash = DottableHash.new({ "foo" => "bar" })
|
12
|
-
dottable_hash.should == { :foo => "bar" }
|
13
|
-
end
|
14
|
-
|
15
|
-
it "initializes new hashes as dottable_hashes" do
|
16
|
-
dottable_hash = DottableHash.new({ :foo => { :bar => "baz" } })
|
17
|
-
dottable_hash[:foo].class.should == DottableHash
|
18
|
-
end
|
19
|
-
|
20
|
-
it "converts all keys to symbols" do
|
21
|
-
dottable_hash = DottableHash.new({ "foo" => { "bar" => "baz" } })
|
22
|
-
dottable_hash.keys.include?(:foo).should be_true
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "#[]" do
|
27
|
-
it "converts keys to strings" do
|
28
|
-
@dottable_hash[:foo] = "bar"
|
29
|
-
@dottable_hash.keys.include?(:foo).should be_true
|
30
|
-
end
|
31
|
-
|
32
|
-
it "converts hash values to dottable_hashs" do
|
33
|
-
@dottable_hash[:foo] = { bar: { baz: "baz" } }
|
34
|
-
@dottable_hash.foo.bar.class.should == DottableHash
|
35
|
-
end
|
36
|
-
|
37
|
-
it "retrieves values by stringified keys" do
|
38
|
-
@dottable_hash["foo"] = "bar"
|
39
|
-
@dottable_hash[:foo].should == "bar"
|
40
|
-
end
|
41
|
-
|
42
|
-
it "converts hashes in arrays to dottable hashes" do
|
43
|
-
pallet = DottableHash.new
|
44
|
-
pallet.foo = [{ bar: "baz" }]
|
45
|
-
pallet.foo.first.class.should == DottableHash
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe "#delete" do
|
50
|
-
it "symbolizes keys" do
|
51
|
-
@dottable_hash["foo"] = { "bar" => "bar", "baz" => "baz" }
|
52
|
-
@dottable_hash.foo.delete(:bar)
|
53
|
-
@dottable_hash.should == { :foo => { :baz => "baz" } }
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe ".has_key?" do
|
58
|
-
it "converts symbols to strings" do
|
59
|
-
DottableHash.new({ foo: "bar" }).has_key?(:foo).should == true
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
describe "#method_missing" do
|
64
|
-
it "returns value for key when it exists" do
|
65
|
-
@dottable_hash[:foo] = "bar"
|
66
|
-
@dottable_hash.foo.should == "bar"
|
67
|
-
end
|
68
|
-
|
69
|
-
it "raises an error when no key exists" do
|
70
|
-
lambda {
|
71
|
-
@dottable_hash.foo
|
72
|
-
}.should raise_error(NoMethodError)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "returns the same object as in the hash" do
|
76
|
-
@dottable_hash[:foo] = { bar: "baz" }
|
77
|
-
dottable_hash_object_id = @dottable_hash.foo.object_id
|
78
|
-
@dottable_hash.foo.object_id.should == dottable_hash_object_id
|
79
|
-
end
|
80
|
-
|
81
|
-
it "sets values" do
|
82
|
-
@dottable_hash.foo = "bar"
|
83
|
-
@dottable_hash.foo.should == "bar"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
describe "dot access" do
|
88
|
-
it "provides acess to keys as methods" do
|
89
|
-
dottable_hash = DottableHash.new({ "foo" => "bar" })
|
90
|
-
dottable_hash.foo.should == "bar"
|
91
|
-
end
|
92
|
-
|
93
|
-
it "provides acess to nested keys as methods" do
|
94
|
-
dottable_hash = DottableHash.new({ "foo" => {"bar" => {"baz" => "bat"}}})
|
95
|
-
dottable_hash.foo.bar.baz.should == "bat"
|
96
|
-
end
|
97
|
-
|
98
|
-
it "provides indifferent accesss" do
|
99
|
-
dottable_hash = DottableHash.new({ :foo => {:bar => {"baz" => "bat"}}})
|
100
|
-
dottable_hash.foo.bar.baz.should == "bat"
|
101
|
-
end
|
102
|
-
|
103
|
-
it "provides acess to keys with nil values" do
|
104
|
-
dottable_hash = DottableHash.new({ "foo" => {"bar" => nil} })
|
105
|
-
dottable_hash.foo.bar.should == nil
|
106
|
-
end
|
107
|
-
|
108
|
-
it "raises key error when it doesn't exist" do
|
109
|
-
dottable_hash = DottableHash.new({ "foo" => "bar" })
|
110
|
-
expect { dottable_hash.fu }.to raise_error(NoMethodError)
|
111
|
-
end
|
112
|
-
|
113
|
-
it "provides the dot access to a hash inside of an array" do
|
114
|
-
dottable_hash = DottableHash.new({ "foo" => [{"bar" => "baz"}]})
|
115
|
-
dottable_hash.foo.first.bar.should == "baz"
|
116
|
-
end
|
117
|
-
|
118
|
-
it "provides the dot access to to a list of strings inside an array" do
|
119
|
-
dottable_hash = DottableHash.new({ "foo" => ["bar", "baz"]})
|
120
|
-
dottable_hash.foo.should == ["bar", "baz"]
|
121
|
-
end
|
122
|
-
|
123
|
-
it "initializes hashes in nested arrays as dottable_hashs" do
|
124
|
-
dottable_hash = DottableHash.new({ foo: [{ bar: [{ baz: "one" }] }] })
|
125
|
-
dottable_hash.foo.first.bar.first.class.should == DottableHash
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe "#fetch" do
|
130
|
-
it "returns dottable_hashs in lieu of hashes" do
|
131
|
-
@dottable_hash["nested_hash"] = { "foo" => "bar" }
|
132
|
-
@dottable_hash.fetch("nested_hash").class.should == DottableHash
|
133
|
-
end
|
134
|
-
|
135
|
-
it "returns value of corresponding key object" do
|
136
|
-
@dottable_hash["foo"] = "bar"
|
137
|
-
@dottable_hash.fetch("foo").should == "bar"
|
138
|
-
end
|
139
|
-
|
140
|
-
it "accepts default value" do
|
141
|
-
DottableHash.new({ baz: "buz" }).fetch(:foo, :bar).should == :bar
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
describe "#fetch_path[!]" do
|
146
|
-
it "returns value of corresponding key object" do
|
147
|
-
@dottable_hash["foo"] = "bar"
|
148
|
-
@dottable_hash.fetch_path("foo").should == "bar"
|
149
|
-
end
|
150
|
-
|
151
|
-
it "returns value of expanded key object" do
|
152
|
-
@dottable_hash["foo"] = { "bar" => "baz" }
|
153
|
-
@dottable_hash.fetch_path("foo.bar").should == "baz"
|
154
|
-
end
|
155
|
-
|
156
|
-
it "raises key errors for nonexistent hashes" do
|
157
|
-
expect {
|
158
|
-
@dottable_hash.fetch_path!("foo")
|
159
|
-
}.to raise_error(KeyError)
|
160
|
-
end
|
161
|
-
|
162
|
-
it "raises key errors when searching into a string" do
|
163
|
-
@dottable_hash["foo"] = "bar"
|
164
|
-
expect {
|
165
|
-
@dottable_hash.fetch_path!("foo.bar")
|
166
|
-
}.to raise_error(KeyError)
|
167
|
-
end
|
168
|
-
|
169
|
-
it "does not raise errors for dottable_hashs with suppressed key errors" do
|
170
|
-
expect {
|
171
|
-
@dottable_hash.fetch_path("foo")
|
172
|
-
}.not_to raise_error
|
173
|
-
|
174
|
-
@dottable_hash["foo"] = "bar"
|
175
|
-
expect {
|
176
|
-
@dottable_hash.fetch_path("foo.bar")
|
177
|
-
}.not_to raise_error
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
describe "#set_path!" do
|
182
|
-
it "sets key's corresponding value" do
|
183
|
-
@dottable_hash.set_path!("foo", "bar")
|
184
|
-
@dottable_hash[:foo].should == "bar"
|
185
|
-
end
|
186
|
-
|
187
|
-
it "sets values for nested paths" do
|
188
|
-
@dottable_hash.set_path!("foo.bar.baz", "i'm really in here!")
|
189
|
-
{
|
190
|
-
:foo => {
|
191
|
-
:bar => {
|
192
|
-
:baz => "i'm really in here!"
|
193
|
-
}
|
194
|
-
}
|
195
|
-
}.should == @dottable_hash
|
196
|
-
end
|
197
|
-
|
198
|
-
it "does not overwrite the root key" do
|
199
|
-
@dottable_hash.set_path!("foo.bar", "bar")
|
200
|
-
@dottable_hash.set_path!("foo.baz.one", "baz1")
|
201
|
-
@dottable_hash.set_path!("foo.baz.two", "baz2")
|
202
|
-
{
|
203
|
-
:foo => {
|
204
|
-
:bar => "bar",
|
205
|
-
:baz => {
|
206
|
-
:one => "baz1",
|
207
|
-
:two => "baz2"
|
208
|
-
}
|
209
|
-
}
|
210
|
-
}.should == @dottable_hash
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
describe "#merge!" do
|
215
|
-
it "works with merged keys as symbols" do
|
216
|
-
dottable_hash = DottableHash.new({ stuff: {} })
|
217
|
-
dottable_hash.stuff.merge!({ things: "widgets" })
|
218
|
-
dottable_hash.stuff.things.should == "widgets"
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
describe "#merge" do
|
223
|
-
it "works with merged keys as symbols" do
|
224
|
-
dottable_hash = DottableHash.new({ stuff: {} })
|
225
|
-
stuff_dottable_hash = dottable_hash.stuff.merge({ things: "widgets" })
|
226
|
-
stuff_dottable_hash.things.should == "widgets"
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
end
|
231
|
-
end
|