dao 3.3.0 → 4.2.1

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 (60) hide show
  1. data/README +7 -0
  2. data/Rakefile +36 -17
  3. data/b.rb +38 -0
  4. data/dao.gemspec +41 -13
  5. data/lib/dao.rb +44 -13
  6. data/lib/dao/api.rb +1 -1
  7. data/lib/dao/api/context.rb +35 -45
  8. data/lib/dao/api/endpoints.rb +225 -91
  9. data/lib/dao/conducer.rb +437 -0
  10. data/lib/dao/conducer/attributes.rb +21 -0
  11. data/lib/dao/conducer/crud.rb +70 -0
  12. data/lib/dao/current.rb +66 -0
  13. data/lib/dao/db.rb +44 -5
  14. data/lib/dao/endpoint.rb +13 -1
  15. data/lib/dao/errors.rb +74 -59
  16. data/lib/dao/exceptions.rb +1 -2
  17. data/lib/dao/extractor.rb +68 -0
  18. data/lib/dao/form.rb +139 -46
  19. data/lib/dao/image_cache.rb +193 -0
  20. data/lib/dao/instance_exec.rb +1 -1
  21. data/lib/dao/name.rb +7 -0
  22. data/lib/dao/params.rb +16 -66
  23. data/lib/dao/rack.rb +3 -0
  24. data/lib/dao/rack/middleware.rb +5 -0
  25. data/lib/dao/rack/middleware/params_parser.rb +24 -0
  26. data/lib/dao/rails.rb +22 -5
  27. data/lib/dao/rails/lib/generators/dao/USAGE +2 -6
  28. data/lib/dao/rails/lib/generators/dao/dao_generator.rb +52 -7
  29. data/lib/dao/rails/lib/generators/dao/templates/api.rb +23 -7
  30. data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +24 -7
  31. data/lib/dao/rails/lib/generators/dao/templates/conducer.rb +64 -0
  32. data/lib/dao/rails/lib/generators/dao/templates/conducer_controller.rb +79 -0
  33. data/lib/dao/rails/lib/generators/dao/templates/dao.js +13 -6
  34. data/lib/dao/rails/lib/generators/dao/templates/dao_helper.rb +75 -11
  35. data/lib/dao/result.rb +1 -26
  36. data/lib/dao/slug.rb +37 -8
  37. data/lib/dao/status.rb +4 -0
  38. data/lib/dao/support.rb +155 -0
  39. data/lib/dao/validations.rb +48 -157
  40. data/lib/dao/validations/callback.rb +30 -0
  41. data/lib/dao/validations/common.rb +322 -320
  42. data/lib/dao/validations/validator.rb +219 -0
  43. data/test/active_model_conducer_lint_test.rb +19 -0
  44. data/test/api_test.rb +261 -0
  45. data/test/conducer_test.rb +205 -0
  46. data/test/db.yml +9 -0
  47. data/test/form_test.rb +42 -0
  48. data/test/support_test.rb +52 -0
  49. data/test/testing.rb +145 -24
  50. data/test/validations_test.rb +156 -0
  51. metadata +138 -21
  52. data/TODO +0 -33
  53. data/a.rb +0 -80
  54. data/db/dao.yml +0 -5
  55. data/lib/dao/api/interfaces.rb +0 -306
  56. data/lib/dao/interface.rb +0 -28
  57. data/lib/dao/presenter.rb +0 -129
  58. data/lib/dao/rails/lib/generators/dao/api_generator.rb +0 -3
  59. data/lib/dao/validations/base.rb +0 -68
  60. data/test/dao_test.rb +0 -506
data/db/dao.yml DELETED
@@ -1,5 +0,0 @@
1
- ---
2
- foo:
3
- "1":
4
- id: 1
5
- bar: 44
@@ -1,306 +0,0 @@
1
- module Dao
2
- class Api
3
- # class methods
4
- #
5
- class << Api
6
- def unload!
7
- state.clear
8
- end
9
-
10
- def state
11
- @state ||= {
12
- :interfaces => {},
13
- :blocks => {},
14
- :README => [],
15
- :docs => []
16
- }
17
- end
18
-
19
- def interface(path, &block)
20
- api = self
21
- path = Path.new(path)
22
-
23
- route = routes.add(path) if Route.like?(path)
24
-
25
- interface = Interface.new({
26
- 'api' => api,
27
- 'path' => path,
28
- 'route' => route,
29
- 'block' => block,
30
- 'doc' => docs.pop
31
- })
32
-
33
- interfaces[path] = interface
34
- end
35
- alias_method('call', 'interface')
36
-
37
- def interfaces
38
- state[:interfaces]
39
- end
40
-
41
- def description(*args)
42
- doc(:description => lines_for(*args))
43
- end
44
- alias_method('desc', 'description')
45
-
46
- def doc(*args)
47
- docs.push(Map[:description, nil]) if docs.empty?
48
- doc = docs.last
49
- options = Dao.options_for!(args)
50
- if options.empty?
51
- options[:description] = lines_for(*args)
52
- end
53
- doc.update(options)
54
- doc
55
- end
56
-
57
- def docs
58
- state[:docs]
59
- end
60
-
61
- def readme(*args)
62
- if args.empty?
63
- state[:README]
64
- else
65
- state[:README] = lines_for(args)
66
- end
67
- end
68
- alias_method('README', 'readme')
69
-
70
- def lines_for(*args)
71
- Dao.unindent(args.flatten.compact.join("\n")).split(/\n/)
72
- end
73
-
74
- def readme=(readme)
75
- self.readme = readme.to_s
76
- end
77
-
78
- def index
79
- index = Map.new
80
- index[:README] = readme
81
- interfaces.each do |path, interface|
82
- index[path] = interface.doc || {'description' => ''}
83
- end
84
- index
85
- end
86
- end
87
-
88
- # instance methods
89
- #
90
-
91
-
92
- # call support
93
- #
94
- def call(path = '/index', params = {}, options = {})
95
- api = self
96
- path = Path.new(path)
97
- interface = interfaces[path] ### interfaces.by_path(path)
98
- route = nil
99
-
100
- unless interface
101
- route = route_for(path)
102
- interface = interfaces[route]
103
- end
104
-
105
- unless interface
106
- return index if path == '/index'
107
- raise(NameError, "NO SUCH INTERFACE: #{ path }")
108
- end
109
-
110
- if route
111
- params.update(route.params_for(path))
112
- path = route.path_for(params)
113
- else
114
- if Route.like?(path)
115
- route = Route.new(path)
116
- path = route.path_for(params)
117
- else
118
- route = path
119
- end
120
- end
121
-
122
- context = Context.for(api, route, path, interface, params, options)
123
-
124
- callstack(context) do
125
- catching(:result) do
126
- context.call()
127
- end
128
- end
129
-
130
- context.result
131
- end
132
-
133
- # lookup a route
134
- #
135
- def route_for(*args)
136
- self.class.routes.match(*args)
137
- end
138
-
139
- # context support
140
- #
141
- def callstack(context = nil, &block)
142
- @callstack ||= []
143
-
144
- if block and context
145
- begin
146
- @callstack.push(context)
147
- return block.call()
148
- ensure
149
- @callstack.pop
150
- end
151
- else
152
- @callstack
153
- end
154
- end
155
-
156
- def context
157
- callstack.last || raise('no context!')
158
- end
159
-
160
- def context?
161
- !!callstack.last
162
- end
163
-
164
- def catching(label = :result, &block)
165
- @catching ||= []
166
-
167
- if block
168
- begin
169
- @catching.push(label)
170
- catch(label, &block)
171
- ensure
172
- @catching.pop
173
- end
174
- else
175
- @catching.last
176
- end
177
- end
178
-
179
- def return!(*value)
180
- throw(:result, *value)
181
- end
182
-
183
- def catching_results(&block)
184
- catching(:result, &block)
185
- end
186
-
187
- def catching?
188
- catching
189
- end
190
-
191
- def catching_results?
192
- catching == :result
193
- end
194
-
195
- # delgate some methods to the context
196
- #
197
- Context.attrs.each do |method|
198
- module_eval <<-__, __FILE__, __LINE__
199
- def #{ method }(*args)
200
- context.send(#{ method.inspect }, *args)
201
- end
202
- __
203
- end
204
-
205
- def status(*args)
206
- context.status.update(*args) unless args.empty?
207
- context.status
208
- end
209
- def status!(*args)
210
- status.update(*args)
211
- return!
212
- end
213
-
214
- def data(*args)
215
- context.data.replace(*args) unless args.empty?
216
- context.data
217
- end
218
- def data!(*args)
219
- data(*args)
220
- valid!
221
- end
222
-
223
- def params!(*args)
224
- params.replace(*args)
225
- valid!
226
- end
227
-
228
- def error!
229
- result.error!
230
- end
231
-
232
- # delegate some methods to the params
233
- #
234
- Validations::Mixin.list.each do |method|
235
- module_eval <<-__, __FILE__, __LINE__
236
- def #{ method }(*args)
237
- params.send(#{ method.inspect }, *args)
238
- end
239
- __
240
- end
241
-
242
- # misc
243
- #
244
- def index
245
- self.class.index
246
- end
247
-
248
- def interfaces
249
- self.class.interfaces
250
- end
251
-
252
- def respond_to?(*args)
253
- super(*args) || super(Path.absolute_path_for(*args))
254
- end
255
-
256
- # immediate parameter parsing support
257
- #
258
- def parameter(*args, &block)
259
- options = Map.options_for!(args)
260
-
261
- keys = args + Array(options[:keys]) + Array(options[:or])
262
-
263
- raise(ArgumentError, 'no keys') if keys.empty?
264
-
265
- blank = Object.new.freeze
266
- value = blank
267
-
268
- keys.each do |key|
269
- if params.has?(key)
270
- value = params.get(key)
271
- break unless value.to_s.strip.empty?
272
- end
273
- end
274
-
275
- if value == blank
276
- message =
277
- case options[:error]
278
- when nil, false
279
- nil
280
- when true
281
- which = keys.map{|key| Array(key).join('.')}.join(' or ')
282
- "#{ which } (parameter is blank)"
283
- else
284
- message = options[:error].to_s
285
- end
286
- errors.add(message) if message
287
-
288
- status(options[:status]) if options[:status]
289
- return! if options[:return!]
290
- end
291
-
292
- value == blank ? nil : value
293
- end
294
- alias_method('param', 'parameter')
295
-
296
- def parameter!(*args, &block)
297
- options = args.last.is_a?(Hash) ? Map.for(args.pop) : Map.new
298
- args.push(options)
299
- options[:error] = true unless options.has_key?(:error)
300
- options[:return!] = true unless options.has_key?(:return!)
301
- options[:status] = 412 unless options.has_key?(:status)
302
- parameter(*args, &block)
303
- end
304
- alias_method('param!', 'parameter!')
305
- end
306
- end
data/lib/dao/interface.rb DELETED
@@ -1,28 +0,0 @@
1
- module Dao
2
- class Interface
3
- Attrs = %w( api path route block doc )
4
- Attrs.each{|attr| attr_accessor(attr)}
5
-
6
- def initialize(options = {})
7
- update(options)
8
- end
9
-
10
- def update(options = {})
11
- options.each do |key, val|
12
- send("#{ key }=", val)
13
- end
14
- end
15
-
16
- def arity
17
- block.arity
18
- end
19
-
20
- def call(*args)
21
- block.call(*args)
22
- end
23
-
24
- def to_proc
25
- block
26
- end
27
- end
28
- end
data/lib/dao/presenter.rb DELETED
@@ -1,129 +0,0 @@
1
- module Dao
2
- class Presenter
3
- include Tagz.globally
4
-
5
- class << Presenter
6
- def for(*args, &block)
7
- new(*args, &block)
8
- end
9
- end
10
-
11
- attr_accessor :result
12
- attr_accessor :formats
13
-
14
- def initialize(*args, &block)
15
- @result = args.shift if args.first.is_a?(Result)
16
- @formats = Map.new
17
- end
18
-
19
- %w( set get has has? [] ).each do |method|
20
- module_eval <<-__, __FILE__, __LINE__
21
- def #{ method }(*args, &block)
22
- data.#{ method }(*args, &block)
23
- end
24
- __
25
- end
26
-
27
- def extend(*args, &block)
28
- return super if block.nil?
29
- singleton_class =
30
- class << self
31
- self
32
- end
33
- singleton_class.module_eval(&block)
34
- end
35
-
36
- def tag(*args, &block)
37
- options = Dao.options_for!(args)
38
- args.push(:div) if args.empty?
39
- tagname = args.shift
40
- keys = args
41
-
42
- tag_method = "#{ tagname }_"
43
-
44
- id = options.delete(:id) || id_for(keys)
45
- klass = class_for(keys, options.delete(:class))
46
- error = error_for(keys, options.delete(:error))
47
-
48
- tag_options =
49
- options_for(options, :id => id, :class => klass, :data_error => error)
50
-
51
- value = value_for(keys)
52
- tag_value = instance_exec(value, &format_for(keys))
53
-
54
- send(tag_method, tag_options){ tag_value }
55
- end
56
-
57
- include InstanceExec
58
-
59
- DefaultFormat = lambda{|value| value}
60
-
61
- def format_for(keys)
62
- formats.get(keys) || DefaultFormat
63
- end
64
-
65
- def format(list_of_keys, &block)
66
- Array(list_of_keys).each do |keys|
67
- formats.set(keys, block)
68
- end
69
- end
70
-
71
- def data
72
- result.data
73
- end
74
-
75
- def errors
76
- result.errors
77
- end
78
-
79
- def ==(other)
80
- result == other.result
81
- end
82
-
83
- def id_for(keys)
84
- id = [result.path, keys.join('-')].compact.join('_')
85
- slug_for(id)
86
- end
87
-
88
- def class_for(keys, klass = nil)
89
- klass =
90
- if result.errors.on?(keys)
91
- [klass, 'dao', 'errors'].compact.join(' ')
92
- else
93
- [klass, 'dao'].compact.join(' ')
94
- end
95
- klass
96
- end
97
-
98
- def error_for(keys, klass = nil)
99
- if result.errors.on?(keys)
100
- result.errors.get(keys)
101
- end
102
- end
103
-
104
- def value_for(keys)
105
- return nil unless data.has?(keys)
106
- value = Tagz.escapeHTML(data.get(keys))
107
- end
108
-
109
- def options_for(*hashes)
110
- map = Map.new
111
- hashes.flatten.each do |h|
112
- h.each{|k,v| map[attr_for(k)] = v unless v.nil?}
113
- end
114
- map
115
- end
116
-
117
- def slug_for(string)
118
- string = string.to_s
119
- words = string.to_s.scan(%r/\w+/)
120
- words.map!{|word| word.gsub(%r/[^0-9a-zA-Z_:-]/, '')}
121
- words.delete_if{|word| word.nil? or word.strip.empty?}
122
- words.join('-').downcase.sub(/_+$/, '')
123
- end
124
-
125
- def attr_for(string)
126
- slug_for(string).gsub(/_/, '-')
127
- end
128
- end
129
- end