restful_objects 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +3 -2
  3. data/bin/restful_server.rb +0 -0
  4. data/lib/restful_objects/action_description.rb +96 -82
  5. data/lib/restful_objects/action_list.rb +17 -17
  6. data/lib/restful_objects/collection_description.rb +47 -47
  7. data/lib/restful_objects/collection_list.rb +17 -17
  8. data/lib/restful_objects/domain_model.rb +83 -79
  9. data/lib/restful_objects/http_response.rb +11 -11
  10. data/lib/restful_objects/link_generator.rb +104 -104
  11. data/lib/restful_objects/object.rb +20 -20
  12. data/lib/restful_objects/object_actions.rb +134 -134
  13. data/lib/restful_objects/object_base.rb +10 -0
  14. data/lib/restful_objects/object_collections.rb +84 -84
  15. data/lib/restful_objects/object_list.rb +16 -16
  16. data/lib/restful_objects/object_macros.rb +35 -35
  17. data/lib/restful_objects/object_properties.rb +78 -78
  18. data/lib/restful_objects/parameter_description.rb +60 -60
  19. data/lib/restful_objects/parameter_description_list.rb +15 -15
  20. data/lib/restful_objects/property_description.rb +68 -68
  21. data/lib/restful_objects/property_list.rb +17 -17
  22. data/lib/restful_objects/service.rb +21 -21
  23. data/lib/restful_objects/service_list.rb +55 -55
  24. data/lib/restful_objects/type.rb +110 -110
  25. data/lib/restful_objects/type_list.rb +30 -30
  26. data/lib/restful_objects/user.rb +30 -30
  27. data/lib/restful_objects/version.rb +1 -1
  28. data/spec/integration/domain-types_actions_spec.rb +43 -43
  29. data/spec/integration/domain-types_collections_spec.rb +45 -45
  30. data/spec/integration/domain-types_properties_spec.rb +41 -41
  31. data/spec/integration/server-root_spec.rb +98 -98
  32. data/spec/spec_helper.rb +52 -52
  33. data/spec/unit/object_actions_spec.rb +380 -380
  34. data/spec/unit/object_collections_spec.rb +190 -190
  35. data/spec/unit/object_properties_spec.rb +215 -206
  36. data/spec/unit/object_spec.rb +228 -228
  37. data/spec/unit/service_spec.rb +125 -125
  38. data/spec/unit/type_list_spec.rb +37 -37
  39. metadata +2 -2
@@ -1,228 +1,228 @@
1
- # encoding: utf-8
2
- require_relative '../spec_helper'
3
-
4
- describe RestfulObjects::Object do
5
- before :all do
6
- RestfulObjects::DomainModel.current.reset
7
-
8
- class Address
9
- include RestfulObjects::Object
10
-
11
- property :street, :string
12
- property :number, :int
13
- end
14
-
15
- class ObjectTest
16
- include RestfulObjects::Object
17
-
18
- property :id, :int, read_only: true
19
- property :password, :string, max_length: 10
20
-
21
- action :hash_password, :string
22
-
23
- collection :addresses, Address
24
-
25
- def initialize
26
- @id = 99
27
- super
28
- end
29
- end
30
- end
31
-
32
- before(:each) do
33
- @object = ObjectTest.new
34
- end
35
-
36
- it 'module should add class macros functionality' do
37
- @object.class.respond_to?(:property).should be_true
38
- @object.class.respond_to?(:action).should be_true
39
- @object.class.respond_to?(:collection).should be_true
40
- end
41
-
42
- it 'should add the type information to the model' do
43
- model.types.include?('ObjectTest').should be_true
44
-
45
- domain_type = model.types['ObjectTest']
46
-
47
- domain_type.properties.include?('id').should be_true
48
- domain_type.properties['id'].return_type.should eq(:int)
49
- domain_type.properties['id'].read_only.should be_true
50
- domain_type.properties['id'].max_length.should be_nil
51
-
52
- domain_type.properties.include?('password').should be_true
53
- domain_type.properties['password'].return_type.should eq(:string)
54
- domain_type.properties['password'].read_only.should be_false
55
- domain_type.properties['password'].max_length.should eq(10)
56
-
57
- domain_type.actions.include?('hash_password').should be_true
58
- domain_type.actions['hash_password'].parameters.count.should eq(0)
59
- domain_type.actions['hash_password'].result_type.should eq(:string)
60
- end
61
-
62
- it 'should generate json for the object' do
63
- @object.password = 'secret_key'
64
- address = Address.new
65
- @object.addresses.push(address)
66
-
67
- expected = {
68
- 'instanceId' => @object.object_id.to_s,
69
- 'title' => "ObjectTest (#{@object.object_id})",
70
- 'members' => {
71
- 'id' =>
72
- { 'memberType' => 'property',
73
- 'value' => 99,
74
- 'disabledReason' => 'read-only property',
75
- 'links' => [
76
- { 'rel' => 'urn:org.restfulobjects:rels/details;property="id"',
77
- 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}/properties/id",
78
- 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object-property"',
79
- 'method' => 'GET' }
80
- ],
81
- 'extensions' => { }
82
- },
83
- 'password' => {
84
- 'memberType' => 'property',
85
- 'value' => 'secret_key',
86
- 'links' => [
87
- { 'rel' => 'urn:org.restfulobjects:rels/details;property="password"',
88
- 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}/properties/password",
89
- 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object-property"',
90
- 'method' => 'GET' }
91
- ],
92
- 'extensions' => { }
93
- },
94
- 'addresses' => {
95
- 'memberType' => 'collection',
96
- 'size' => 1,
97
- 'links' => [
98
- { 'rel' => 'urn:org.restfulobjects:rels/details;collection="addresses"',
99
- 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}/collections/addresses",
100
- 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object-collection"',
101
- 'method' => 'GET' }
102
- ],
103
- 'extensions' => { }
104
- },
105
- 'hash_password' => {
106
- 'memberType' => 'action',
107
- 'links' => [
108
- { 'rel' => 'urn:org.restfulobjects:rels/details;action="hash_password"',
109
- 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}/actions/hash_password",
110
- 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object-action"',
111
- 'method' => 'GET' }
112
- ],
113
- 'extensions' => { }
114
- }
115
- },
116
- 'links' => [
117
- { 'rel' => 'self',
118
- 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}",
119
- 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object"',
120
- 'method' => 'GET' },
121
- { 'rel' => 'describedby',
122
- 'href' => "http://localhost/domain-types/ObjectTest",
123
- 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/domain-type"',
124
- 'method' => 'GET' }
125
- ],
126
- 'extensions' => wildcard_matcher
127
- }
128
-
129
- get "/objects/ObjectTest/#{@object.object_id}"
130
-
131
- last_response.body.should match_json_expression expected
132
- last_response.content_type.should eq 'application/json;profile="urn:org.restfulobjects:repr-types/object";x-ro-domain-type="ObjectTest"'
133
- end
134
-
135
- it 'should generate metadata in extensions' do
136
- @object.rs_type.plural_name = 'Test Objects'
137
- @object.rs_type.friendly_name = 'Test Object Friendly'
138
- @object.rs_type.description = 'An object to test'
139
-
140
- expected = {
141
- 'instanceId' => @object.object_id.to_s,
142
- 'extensions' => {
143
- 'domainType' => 'ObjectTest',
144
- 'pluralName' => 'Test Objects',
145
- 'friendlyName' => 'Test Object Friendly',
146
- 'description' => 'An object to test',
147
- 'isService' => false
148
- }.strict!
149
- }
150
-
151
- get "/objects/ObjectTest/#{@object.object_id}"
152
-
153
- last_response.body.should match_json_expression expected
154
- end
155
-
156
- it 'should call initialize on object' do
157
- class InitializedObject
158
- include RestfulObjects::Object
159
- attr_reader :init_called
160
- def initialize
161
- super
162
- @init_called = true
163
- @title = 'A title'
164
- end
165
- end
166
- obj = InitializedObject.new
167
- obj.init_called.should be_true
168
- obj.title.should eq 'A title'
169
- end
170
-
171
- it 'should send on_after_create callback when object is created' do
172
- class CreatedObject
173
- include RestfulObjects::Object
174
- attr_reader :called
175
- def on_after_create
176
- @called = true
177
- end
178
- end
179
-
180
- CreatedObject.new.called.should be_true
181
- end
182
-
183
- it 'should send on_after_update callback when object property is updated or deleted' do
184
- class UpdatableObject
185
- include RestfulObjects::Object
186
- attr_accessor :prop_updated
187
- property :data, :string
188
- def on_after_update
189
- @prop_updated = true
190
- end
191
- end
192
-
193
- obj = UpdatableObject.new
194
-
195
- obj.prop_updated.should_not be_true
196
-
197
- put "/objects/UpdatableObject/#{obj.object_id}/properties/data", {}, { input: { 'value' => 'irrelevant' }.to_json }
198
-
199
- obj.prop_updated.should be_true
200
-
201
- obj.prop_updated = false
202
-
203
- delete "/objects/UpdatableObject/#{obj.object_id}/properties/data"
204
-
205
- obj.prop_updated.should be_true
206
- end
207
-
208
- it 'should send on_after_delete callback when object is deleted' do
209
- class DeletedObject
210
- include RestfulObjects::Object
211
- attr_reader :destroyed
212
- def on_after_delete
213
- @destroyed = true
214
- end
215
- end
216
-
217
- obj = DeletedObject.new
218
-
219
- obj.deleted?.should_not be_true
220
- obj.destroyed.should_not be_true
221
-
222
- delete "/objects/DeletedObject/#{obj.object_id}"
223
-
224
- obj.deleted?.should be_true
225
- obj.destroyed.should be_true
226
- end
227
- end
228
-
1
+ # encoding: utf-8
2
+ require_relative '../spec_helper'
3
+
4
+ describe RestfulObjects::Object do
5
+ before :all do
6
+ RestfulObjects::DomainModel.current.reset
7
+
8
+ class Address
9
+ include RestfulObjects::Object
10
+
11
+ property :street, :string
12
+ property :number, :int
13
+ end
14
+
15
+ class ObjectTest
16
+ include RestfulObjects::Object
17
+
18
+ property :id, :int, read_only: true
19
+ property :password, :string, max_length: 10
20
+
21
+ action :hash_password, return_type: :string
22
+
23
+ collection :addresses, Address
24
+
25
+ def initialize
26
+ @id = 99
27
+ super
28
+ end
29
+ end
30
+ end
31
+
32
+ before(:each) do
33
+ @object = ObjectTest.new
34
+ end
35
+
36
+ it 'module should add class macros functionality' do
37
+ @object.class.respond_to?(:property).should be_true
38
+ @object.class.respond_to?(:action).should be_true
39
+ @object.class.respond_to?(:collection).should be_true
40
+ end
41
+
42
+ it 'should add the type information to the model' do
43
+ model.types.include?('ObjectTest').should be_true
44
+
45
+ domain_type = model.types['ObjectTest']
46
+
47
+ domain_type.properties.include?('id').should be_true
48
+ domain_type.properties['id'].return_type.should eq(:int)
49
+ domain_type.properties['id'].read_only.should be_true
50
+ domain_type.properties['id'].max_length.should be_nil
51
+
52
+ domain_type.properties.include?('password').should be_true
53
+ domain_type.properties['password'].return_type.should eq(:string)
54
+ domain_type.properties['password'].read_only.should be_false
55
+ domain_type.properties['password'].max_length.should eq(10)
56
+
57
+ domain_type.actions.include?('hash_password').should be_true
58
+ domain_type.actions['hash_password'].parameters.count.should eq(0)
59
+ domain_type.actions['hash_password'].result_type.should eq(:string)
60
+ end
61
+
62
+ it 'should generate json for the object' do
63
+ @object.password = 'secret_key'
64
+ address = Address.new
65
+ @object.addresses.push(address)
66
+
67
+ expected = {
68
+ 'instanceId' => @object.object_id.to_s,
69
+ 'title' => "ObjectTest (#{@object.object_id})",
70
+ 'members' => {
71
+ 'id' =>
72
+ { 'memberType' => 'property',
73
+ 'value' => 99,
74
+ 'disabledReason' => 'read-only property',
75
+ 'links' => [
76
+ { 'rel' => 'urn:org.restfulobjects:rels/details;property="id"',
77
+ 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}/properties/id",
78
+ 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object-property"',
79
+ 'method' => 'GET' }
80
+ ],
81
+ 'extensions' => { }
82
+ },
83
+ 'password' => {
84
+ 'memberType' => 'property',
85
+ 'value' => 'secret_key',
86
+ 'links' => [
87
+ { 'rel' => 'urn:org.restfulobjects:rels/details;property="password"',
88
+ 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}/properties/password",
89
+ 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object-property"',
90
+ 'method' => 'GET' }
91
+ ],
92
+ 'extensions' => { }
93
+ },
94
+ 'addresses' => {
95
+ 'memberType' => 'collection',
96
+ 'size' => 1,
97
+ 'links' => [
98
+ { 'rel' => 'urn:org.restfulobjects:rels/details;collection="addresses"',
99
+ 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}/collections/addresses",
100
+ 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object-collection"',
101
+ 'method' => 'GET' }
102
+ ],
103
+ 'extensions' => { }
104
+ },
105
+ 'hash_password' => {
106
+ 'memberType' => 'action',
107
+ 'links' => [
108
+ { 'rel' => 'urn:org.restfulobjects:rels/details;action="hash_password"',
109
+ 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}/actions/hash_password",
110
+ 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object-action"',
111
+ 'method' => 'GET' }
112
+ ],
113
+ 'extensions' => { }
114
+ }
115
+ },
116
+ 'links' => [
117
+ { 'rel' => 'self',
118
+ 'href' => "http://localhost/objects/ObjectTest/#{@object.object_id}",
119
+ 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/object"',
120
+ 'method' => 'GET' },
121
+ { 'rel' => 'describedby',
122
+ 'href' => "http://localhost/domain-types/ObjectTest",
123
+ 'type' => 'application/json;profile="urn:org.restfulobjects:repr-types/domain-type"',
124
+ 'method' => 'GET' }
125
+ ],
126
+ 'extensions' => wildcard_matcher
127
+ }
128
+
129
+ get "/objects/ObjectTest/#{@object.object_id}"
130
+
131
+ last_response.body.should match_json_expression expected
132
+ last_response.content_type.should eq 'application/json;profile="urn:org.restfulobjects:repr-types/object";x-ro-domain-type="ObjectTest"'
133
+ end
134
+
135
+ it 'should generate metadata in extensions' do
136
+ @object.rs_type.plural_name = 'Test Objects'
137
+ @object.rs_type.friendly_name = 'Test Object Friendly'
138
+ @object.rs_type.description = 'An object to test'
139
+
140
+ expected = {
141
+ 'instanceId' => @object.object_id.to_s,
142
+ 'extensions' => {
143
+ 'domainType' => 'ObjectTest',
144
+ 'pluralName' => 'Test Objects',
145
+ 'friendlyName' => 'Test Object Friendly',
146
+ 'description' => 'An object to test',
147
+ 'isService' => false
148
+ }.strict!
149
+ }
150
+
151
+ get "/objects/ObjectTest/#{@object.object_id}"
152
+
153
+ last_response.body.should match_json_expression expected
154
+ end
155
+
156
+ it 'should call initialize on object' do
157
+ class InitializedObject
158
+ include RestfulObjects::Object
159
+ attr_reader :init_called
160
+ def initialize
161
+ super
162
+ @init_called = true
163
+ @title = 'A title'
164
+ end
165
+ end
166
+ obj = InitializedObject.new
167
+ obj.init_called.should be_true
168
+ obj.title.should eq 'A title'
169
+ end
170
+
171
+ it 'should send on_after_create callback when object is created' do
172
+ class CreatedObject
173
+ include RestfulObjects::Object
174
+ attr_reader :called
175
+ def on_after_create
176
+ @called = true
177
+ end
178
+ end
179
+
180
+ CreatedObject.new.called.should be_true
181
+ end
182
+
183
+ it 'should send on_after_update callback when object property is updated or deleted' do
184
+ class UpdatableObject
185
+ include RestfulObjects::Object
186
+ attr_accessor :prop_updated
187
+ property :data, :string
188
+ def on_after_update
189
+ @prop_updated = true
190
+ end
191
+ end
192
+
193
+ obj = UpdatableObject.new
194
+
195
+ obj.prop_updated.should_not be_true
196
+
197
+ put "/objects/UpdatableObject/#{obj.object_id}/properties/data", {}, { input: { 'value' => 'irrelevant' }.to_json }
198
+
199
+ obj.prop_updated.should be_true
200
+
201
+ obj.prop_updated = false
202
+
203
+ delete "/objects/UpdatableObject/#{obj.object_id}/properties/data"
204
+
205
+ obj.prop_updated.should be_true
206
+ end
207
+
208
+ it 'should send on_after_delete callback when object is deleted' do
209
+ class DeletedObject
210
+ include RestfulObjects::Object
211
+ attr_reader :destroyed
212
+ def on_after_delete
213
+ @destroyed = true
214
+ end
215
+ end
216
+
217
+ obj = DeletedObject.new
218
+
219
+ obj.deleted?.should_not be_true
220
+ obj.destroyed.should_not be_true
221
+
222
+ delete "/objects/DeletedObject/#{obj.object_id}"
223
+
224
+ obj.deleted?.should be_true
225
+ obj.destroyed.should be_true
226
+ end
227
+ end
228
+