dao 3.3.0 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
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