restful_objects 0.0.2 → 0.0.3

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.
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
+