sinatra_resource 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/VERSION +1 -1
  2. data/examples/datacatalog/lib/resource.rb +2 -2
  3. data/examples/datacatalog/lib/roles.rb +1 -1
  4. data/examples/datacatalog/resources/categories_sources.rb +43 -0
  5. data/examples/datacatalog/test/helpers/lib/request_helpers.rb +10 -2
  6. data/examples/datacatalog/test/helpers/resource_test_helper.rb +1 -1
  7. data/examples/datacatalog/test/helpers/shared/api_keys.rb +4 -4
  8. data/examples/datacatalog/test/helpers/shared/model_counts.rb +81 -0
  9. data/examples/datacatalog/test/helpers/shared/status_codes.rb +7 -3
  10. data/examples/datacatalog/test/helpers/test_helper.rb +2 -9
  11. data/examples/datacatalog/test/resources/categories/categories_delete_test.rb +5 -17
  12. data/examples/datacatalog/test/resources/categories/categories_get_many_test.rb +5 -2
  13. data/examples/datacatalog/test/resources/categories/categories_get_one_test.rb +4 -3
  14. data/examples/datacatalog/test/resources/categories/categories_post_test.rb +27 -43
  15. data/examples/datacatalog/test/resources/categories/categories_put_test.rb +9 -15
  16. data/examples/datacatalog/test/resources/categories_sources/categories_sources_delete_test.rb +148 -0
  17. data/examples/datacatalog/test/resources/categories_sources/categories_sources_get_many_test.rb +92 -0
  18. data/examples/datacatalog/test/resources/categories_sources/categories_sources_get_one_test.rb +95 -0
  19. data/examples/datacatalog/test/resources/categories_sources/categories_sources_post_test.rb +187 -0
  20. data/examples/datacatalog/test/resources/categories_sources/categories_sources_put_test.rb +323 -0
  21. data/examples/datacatalog/test/resources/sources/sources_delete_test.rb +5 -17
  22. data/examples/datacatalog/test/resources/sources/sources_get_many_test.rb +5 -2
  23. data/examples/datacatalog/test/resources/sources/sources_get_one_test.rb +4 -3
  24. data/examples/datacatalog/test/resources/sources/sources_post_test.rb +22 -35
  25. data/examples/datacatalog/test/resources/sources/sources_put_test.rb +12 -18
  26. data/examples/datacatalog/test/resources/users/users_delete_test.rb +10 -22
  27. data/examples/datacatalog/test/resources/users/users_get_many_test.rb +5 -2
  28. data/examples/datacatalog/test/resources/users/users_get_one_test.rb +4 -3
  29. data/examples/datacatalog/test/resources/users/users_post_test.rb +15 -32
  30. data/examples/datacatalog/test/resources/users/users_put_test.rb +15 -23
  31. data/lib/builder/action_definitions.rb +60 -0
  32. data/lib/builder/helpers.rb +53 -26
  33. data/lib/builder/mongo_helpers.rb +61 -10
  34. data/lib/builder.rb +136 -38
  35. data/lib/resource.rb +99 -16
  36. data/lib/sinatra_resource.rb +6 -6
  37. data/notes/permissions.mdown +6 -6
  38. data/sinatra_resource.gemspec +17 -2
  39. metadata +17 -2
data/lib/resource.rb CHANGED
@@ -6,12 +6,28 @@ module SinatraResource
6
6
  includee.setup
7
7
  end
8
8
 
9
- def config
10
- self.class.instance_variable_get("@resource_config")
9
+ def resource_config
10
+ self.class.resource_config
11
11
  end
12
-
12
+
13
13
  module ClassMethods
14
14
 
15
+ attr_reader :resource_config
16
+
17
+ # Specify the association +method+ on +parent+ that points to the
18
+ # current (child) +model+.
19
+ #
20
+ # @param [Symbol] method
21
+ # A symbol that refers to a method on the parent.
22
+ #
23
+ # @return [undefined]
24
+ def child_association(method)
25
+ if @resource_config[:child_association]
26
+ raise DefinitionError, "child_association already declared in #{self}"
27
+ end
28
+ @resource_config[:child_association] = method
29
+ end
30
+
15
31
  # Build the Sinatra actions based on the DSL statements in this class.
16
32
  # You will want to do this last.
17
33
  #
@@ -20,10 +36,11 @@ module SinatraResource
20
36
  #
21
37
  # @return [undefined]
22
38
  def build
39
+ deferred_defaults
23
40
  validate
24
41
  Builder.new(self).build
25
42
  end
26
-
43
+
27
44
  # Specify the underlying +model+
28
45
  #
29
46
  # @example
@@ -43,7 +60,33 @@ module SinatraResource
43
60
  raise DefinitionError, "model already declared in #{self}"
44
61
  end
45
62
  @resource_config[:model] = model
46
- default_properties
63
+ end
64
+
65
+ # Specify the parent +resource+. Only used for nested resources.
66
+ #
67
+ # @param [Class] resource
68
+ #
69
+ # @return [undefined]
70
+ def parent(resource)
71
+ if @resource_config[:parent]
72
+ raise DefinitionError, "parent already declared in #{self}"
73
+ end
74
+ @resource_config[:parent] = resource
75
+ end
76
+
77
+ # Specify the path. If not specified, SinatraResource will infer the path
78
+ # from the resource class (see the +default_path+ method.)
79
+ #
80
+ # This method is also useful for nested resources.
81
+ #
82
+ # @param [String] name
83
+ #
84
+ # @return [undefined]
85
+ def path(name)
86
+ if @resource_config[:path]
87
+ raise DefinitionError, "path already declared in #{self}"
88
+ end
89
+ @resource_config[:path] = name
47
90
  end
48
91
 
49
92
  # Specify the minimal role needed to access this resource for reading
@@ -78,7 +121,7 @@ module SinatraResource
78
121
  # @return [undefined]
79
122
  def property(name, access_rules={}, &block)
80
123
  if @resource_config[:properties][name]
81
- raise DefinitionError, "property #{name} already declared in #{self}"
124
+ raise DefinitionError, "property #{name.inspect} already declared in #{self}"
82
125
  end
83
126
  @resource_config[:properties][name] = {}
84
127
  if block
@@ -91,6 +134,33 @@ module SinatraResource
91
134
  end
92
135
  end
93
136
 
137
+ # Declare a relation with a block of code.
138
+ #
139
+ # Only needed with nested resources.
140
+ #
141
+ # For example:
142
+ # relation :create do |parent, child|
143
+ # Categorization.create(
144
+ # :category_id => parent.id,
145
+ # :source_id => child.id
146
+ # )
147
+ # end
148
+ #
149
+ # This runs after a POST to automatically connect parent with child.
150
+ #
151
+ # Is useful to create a document that joins a category (the parent)
152
+ # to the source (the child).
153
+ #
154
+ # @param [Symbol] name
155
+ #
156
+ # @return [undefined]
157
+ def relation(name, &block)
158
+ if @resource_config[:relation][name]
159
+ raise DefinitionError, "relation #{name.inspect} already declared in #{self}"
160
+ end
161
+ @resource_config[:relation][name] = block
162
+ end
163
+
94
164
  # Specify the role definitions for this resource.
95
165
  #
96
166
  # @example
@@ -118,28 +188,41 @@ module SinatraResource
118
188
  # For internal use. Initializes internal data structure.
119
189
  def setup
120
190
  @resource_config = {
121
- :model => nil,
122
- :permission => {},
123
- :properties => {},
124
- :roles => nil,
125
- :path => default_path,
191
+ :child_association => nil,
192
+ :model => nil,
193
+ :parent => nil,
194
+ :path => nil, # default_path,
195
+ :permission => {},
196
+ :properties => {},
197
+ :relation => { :create => nil, :delete => nil },
198
+ :roles => nil,
126
199
  }
127
200
  end
128
201
 
129
202
  protected
130
203
 
131
- # Return the default relative path for a resource.
204
+ # Set some defaults, only if they haven't been set already.
205
+ #
206
+ # @return [undefined]
207
+ def deferred_defaults
208
+ set_default_path
209
+ set_default_properties
210
+ end
211
+
212
+ # Set the default relative path for a resource.
132
213
  #
133
- # @return [String]
134
- def default_path
135
- self.to_s.split('::').last.downcase
214
+ # @return [undefined]
215
+ def set_default_path
216
+ unless @resource_config[:path]
217
+ @resource_config[:path] = self.to_s.split('::').last.downcase
218
+ end
136
219
  end
137
220
 
138
221
  # Define some default properties to mirror common keys in the
139
222
  # model
140
223
  #
141
224
  # @return [undefined]
142
- def default_properties
225
+ def set_default_properties
143
226
  keys = @resource_config[:model].keys
144
227
  if keys.include?("_id")
145
228
  property :id, :w => :nobody
@@ -1,6 +1,6 @@
1
- require File.dirname(__FILE__) + '/exceptions'
2
- require File.dirname(__FILE__) + '/builder/helpers'
3
- require File.dirname(__FILE__) + '/builder/mongo_helpers'
4
- require File.dirname(__FILE__) + '/builder'
5
- require File.dirname(__FILE__) + '/resource'
6
- require File.dirname(__FILE__) + '/roles'
1
+ base = File.dirname(__FILE__)
2
+ require base + '/exceptions'
3
+ Dir.glob(base + '/builder/*.rb').each { |f| require f }
4
+ require base + '/builder'
5
+ require base + '/resource'
6
+ require base + '/roles'
@@ -68,11 +68,11 @@ In other words, if you know the user type, action, and resource, you
68
68
  know whether to allow or disallow.
69
69
 
70
70
  def allow?(user_type, action, resource)
71
- # logic depends solely on parameters
71
+ # logic depends solely on params
72
72
  end
73
73
 
74
74
  def disallow?(user_type, action, resource)
75
- # logic depends solely on parameters
75
+ # logic depends solely on params
76
76
  end
77
77
 
78
78
  ## Document-level use cases:
@@ -145,21 +145,21 @@ The nice thing about the {can | can't} style is that it allows for one or both
145
145
  Which brings us back to the 'allow?' and 'disallow?' methods:
146
146
 
147
147
  def allow?(user_type, user, action, resource, instance, relation)
148
- # logic depends solely on parameters
148
+ # logic depends solely on params
149
149
  end
150
150
 
151
151
  def disallow?(user_type, user, action, resource, instance, relation)
152
- # logic depends solely on parameters
152
+ # logic depends solely on params
153
153
  end
154
154
 
155
155
  I would expect that user_type can be derived from user, so we can simplify:
156
156
 
157
157
  def allow?(user, action, resource, instance, relation)
158
- # logic depends solely on parameters
158
+ # logic depends solely on params
159
159
  end
160
160
 
161
161
  def disallow?(user, action, resource, instance, relation)
162
- # logic depends solely on parameters
162
+ # logic depends solely on params
163
163
  end
164
164
 
165
165
  It is tempting to try to simplify further. For example, why not assume that resource can be inferred from instance? That may be so, but I'm not so convinced that there is only one resource for each instance. For example,
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{sinatra_resource}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["David James"]
12
- s.date = %q{2009-10-20}
12
+ s.date = %q{2009-10-22}
13
13
  s.description = %q{A DSL for creating RESTful actions with Sinatra and MongoMapper. It embraces the Resource Oriented Architecture as explained by Leonard Richardson and Sam Ruby.}
14
14
  s.email = %q{djames@sunlightfoundation.com}
15
15
  s.extra_rdoc_files = [
@@ -36,6 +36,7 @@ Gem::Specification.new do |s|
36
36
  "examples/datacatalog/models/source.rb",
37
37
  "examples/datacatalog/models/user.rb",
38
38
  "examples/datacatalog/resources/categories.rb",
39
+ "examples/datacatalog/resources/categories_sources.rb",
39
40
  "examples/datacatalog/resources/sources.rb",
40
41
  "examples/datacatalog/resources/users.rb",
41
42
  "examples/datacatalog/tasks/db.rake",
@@ -49,6 +50,7 @@ Gem::Specification.new do |s|
49
50
  "examples/datacatalog/test/helpers/resource_test_helper.rb",
50
51
  "examples/datacatalog/test/helpers/shared/api_keys.rb",
51
52
  "examples/datacatalog/test/helpers/shared/common_body_responses.rb",
53
+ "examples/datacatalog/test/helpers/shared/model_counts.rb",
52
54
  "examples/datacatalog/test/helpers/shared/status_codes.rb",
53
55
  "examples/datacatalog/test/helpers/test_cases/model_test_case.rb",
54
56
  "examples/datacatalog/test/helpers/test_cases/resource_test_case.rb",
@@ -62,6 +64,11 @@ Gem::Specification.new do |s|
62
64
  "examples/datacatalog/test/resources/categories/categories_get_one_test.rb",
63
65
  "examples/datacatalog/test/resources/categories/categories_post_test.rb",
64
66
  "examples/datacatalog/test/resources/categories/categories_put_test.rb",
67
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_delete_test.rb",
68
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_get_many_test.rb",
69
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_get_one_test.rb",
70
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_post_test.rb",
71
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_put_test.rb",
65
72
  "examples/datacatalog/test/resources/sources/sources_delete_test.rb",
66
73
  "examples/datacatalog/test/resources/sources/sources_get_many_test.rb",
67
74
  "examples/datacatalog/test/resources/sources/sources_get_one_test.rb",
@@ -73,6 +80,7 @@ Gem::Specification.new do |s|
73
80
  "examples/datacatalog/test/resources/users/users_post_test.rb",
74
81
  "examples/datacatalog/test/resources/users/users_put_test.rb",
75
82
  "lib/builder.rb",
83
+ "lib/builder/action_definitions.rb",
76
84
  "lib/builder/helpers.rb",
77
85
  "lib/builder/mongo_helpers.rb",
78
86
  "lib/exceptions.rb",
@@ -110,6 +118,7 @@ Gem::Specification.new do |s|
110
118
  "examples/datacatalog/models/source.rb",
111
119
  "examples/datacatalog/models/user.rb",
112
120
  "examples/datacatalog/resources/categories.rb",
121
+ "examples/datacatalog/resources/categories_sources.rb",
113
122
  "examples/datacatalog/resources/sources.rb",
114
123
  "examples/datacatalog/resources/users.rb",
115
124
  "examples/datacatalog/test/helpers/assertions/assert_include.rb",
@@ -121,6 +130,7 @@ Gem::Specification.new do |s|
121
130
  "examples/datacatalog/test/helpers/resource_test_helper.rb",
122
131
  "examples/datacatalog/test/helpers/shared/api_keys.rb",
123
132
  "examples/datacatalog/test/helpers/shared/common_body_responses.rb",
133
+ "examples/datacatalog/test/helpers/shared/model_counts.rb",
124
134
  "examples/datacatalog/test/helpers/shared/status_codes.rb",
125
135
  "examples/datacatalog/test/helpers/test_cases/model_test_case.rb",
126
136
  "examples/datacatalog/test/helpers/test_cases/resource_test_case.rb",
@@ -134,6 +144,11 @@ Gem::Specification.new do |s|
134
144
  "examples/datacatalog/test/resources/categories/categories_get_one_test.rb",
135
145
  "examples/datacatalog/test/resources/categories/categories_post_test.rb",
136
146
  "examples/datacatalog/test/resources/categories/categories_put_test.rb",
147
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_delete_test.rb",
148
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_get_many_test.rb",
149
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_get_one_test.rb",
150
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_post_test.rb",
151
+ "examples/datacatalog/test/resources/categories_sources/categories_sources_put_test.rb",
137
152
  "examples/datacatalog/test/resources/sources/sources_delete_test.rb",
138
153
  "examples/datacatalog/test/resources/sources/sources_get_many_test.rb",
139
154
  "examples/datacatalog/test/resources/sources/sources_get_one_test.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra_resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David James
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-20 00:00:00 -04:00
12
+ date: 2009-10-22 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -121,6 +121,7 @@ files:
121
121
  - examples/datacatalog/models/source.rb
122
122
  - examples/datacatalog/models/user.rb
123
123
  - examples/datacatalog/resources/categories.rb
124
+ - examples/datacatalog/resources/categories_sources.rb
124
125
  - examples/datacatalog/resources/sources.rb
125
126
  - examples/datacatalog/resources/users.rb
126
127
  - examples/datacatalog/tasks/db.rake
@@ -134,6 +135,7 @@ files:
134
135
  - examples/datacatalog/test/helpers/resource_test_helper.rb
135
136
  - examples/datacatalog/test/helpers/shared/api_keys.rb
136
137
  - examples/datacatalog/test/helpers/shared/common_body_responses.rb
138
+ - examples/datacatalog/test/helpers/shared/model_counts.rb
137
139
  - examples/datacatalog/test/helpers/shared/status_codes.rb
138
140
  - examples/datacatalog/test/helpers/test_cases/model_test_case.rb
139
141
  - examples/datacatalog/test/helpers/test_cases/resource_test_case.rb
@@ -147,6 +149,11 @@ files:
147
149
  - examples/datacatalog/test/resources/categories/categories_get_one_test.rb
148
150
  - examples/datacatalog/test/resources/categories/categories_post_test.rb
149
151
  - examples/datacatalog/test/resources/categories/categories_put_test.rb
152
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_delete_test.rb
153
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_get_many_test.rb
154
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_get_one_test.rb
155
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_post_test.rb
156
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_put_test.rb
150
157
  - examples/datacatalog/test/resources/sources/sources_delete_test.rb
151
158
  - examples/datacatalog/test/resources/sources/sources_get_many_test.rb
152
159
  - examples/datacatalog/test/resources/sources/sources_get_one_test.rb
@@ -158,6 +165,7 @@ files:
158
165
  - examples/datacatalog/test/resources/users/users_post_test.rb
159
166
  - examples/datacatalog/test/resources/users/users_put_test.rb
160
167
  - lib/builder.rb
168
+ - lib/builder/action_definitions.rb
161
169
  - lib/builder/helpers.rb
162
170
  - lib/builder/mongo_helpers.rb
163
171
  - lib/exceptions.rb
@@ -217,6 +225,7 @@ test_files:
217
225
  - examples/datacatalog/models/source.rb
218
226
  - examples/datacatalog/models/user.rb
219
227
  - examples/datacatalog/resources/categories.rb
228
+ - examples/datacatalog/resources/categories_sources.rb
220
229
  - examples/datacatalog/resources/sources.rb
221
230
  - examples/datacatalog/resources/users.rb
222
231
  - examples/datacatalog/test/helpers/assertions/assert_include.rb
@@ -228,6 +237,7 @@ test_files:
228
237
  - examples/datacatalog/test/helpers/resource_test_helper.rb
229
238
  - examples/datacatalog/test/helpers/shared/api_keys.rb
230
239
  - examples/datacatalog/test/helpers/shared/common_body_responses.rb
240
+ - examples/datacatalog/test/helpers/shared/model_counts.rb
231
241
  - examples/datacatalog/test/helpers/shared/status_codes.rb
232
242
  - examples/datacatalog/test/helpers/test_cases/model_test_case.rb
233
243
  - examples/datacatalog/test/helpers/test_cases/resource_test_case.rb
@@ -241,6 +251,11 @@ test_files:
241
251
  - examples/datacatalog/test/resources/categories/categories_get_one_test.rb
242
252
  - examples/datacatalog/test/resources/categories/categories_post_test.rb
243
253
  - examples/datacatalog/test/resources/categories/categories_put_test.rb
254
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_delete_test.rb
255
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_get_many_test.rb
256
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_get_one_test.rb
257
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_post_test.rb
258
+ - examples/datacatalog/test/resources/categories_sources/categories_sources_put_test.rb
244
259
  - examples/datacatalog/test/resources/sources/sources_delete_test.rb
245
260
  - examples/datacatalog/test/resources/sources/sources_get_many_test.rb
246
261
  - examples/datacatalog/test/resources/sources/sources_get_one_test.rb