dao 4.2.1 → 4.4.2

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 (78) hide show
  1. data/README +103 -63
  2. data/Rakefile +3 -3
  3. data/dao.gemspec +27 -16
  4. data/lib/dao.rb +17 -17
  5. data/lib/dao/active_record.rb +1 -0
  6. data/lib/dao/api.rb +2 -1
  7. data/lib/dao/api/{endpoints.rb → call.rb} +1 -0
  8. data/lib/dao/api/context.rb +2 -0
  9. data/lib/dao/api/dsl.rb +1 -0
  10. data/lib/dao/api/initializers.rb +1 -0
  11. data/lib/dao/api/modes.rb +1 -0
  12. data/lib/dao/api/routes.rb +1 -0
  13. data/lib/dao/blankslate.rb +1 -0
  14. data/lib/dao/conducer.rb +315 -274
  15. data/lib/dao/conducer/active_model.rb +98 -0
  16. data/lib/dao/conducer/attributes.rb +1 -0
  17. data/lib/dao/conducer/autocrud.rb +58 -0
  18. data/lib/dao/conducer/callback_support.rb +20 -0
  19. data/lib/dao/conducer/collection.rb +45 -0
  20. data/lib/dao/conducer/controller_support.rb +104 -0
  21. data/lib/dao/conducer/nav_support.rb +9 -0
  22. data/lib/dao/conducer/view_support.rb +16 -0
  23. data/lib/dao/data.rb +2 -1
  24. data/lib/dao/db.rb +2 -0
  25. data/lib/dao/endpoint.rb +1 -0
  26. data/lib/dao/engine.rb +1 -0
  27. data/lib/dao/errors.rb +109 -99
  28. data/lib/dao/exceptions.rb +1 -0
  29. data/lib/dao/extractor.rb +1 -0
  30. data/lib/dao/form.rb +175 -20
  31. data/lib/dao/instance_exec.rb +1 -0
  32. data/lib/dao/mode.rb +1 -0
  33. data/lib/dao/mongo_mapper.rb +1 -0
  34. data/lib/dao/name.rb +1 -0
  35. data/lib/dao/params.rb +2 -1
  36. data/lib/dao/path.rb +1 -0
  37. data/lib/dao/path_map.rb +24 -0
  38. data/lib/dao/rack.rb +1 -0
  39. data/lib/dao/rack/middleware.rb +1 -0
  40. data/lib/dao/rack/middleware/params_parser.rb +1 -0
  41. data/lib/dao/rails.rb +12 -32
  42. data/lib/dao/rails/lib/generators/dao/USAGE +2 -2
  43. data/lib/dao/rails/lib/generators/dao/dao_generator.rb +8 -27
  44. data/lib/dao/rails/lib/generators/dao/templates/api.rb +2 -1
  45. data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +22 -20
  46. data/lib/dao/rails/lib/generators/dao/templates/conducer.rb +49 -43
  47. data/lib/dao/rails/lib/generators/dao/templates/dao.css +26 -25
  48. data/lib/dao/rails/lib/generators/dao/templates/dao.js +3 -0
  49. data/lib/dao/rails/lib/generators/dao/templates/dao_helper.rb +58 -45
  50. data/lib/dao/result.rb +50 -1
  51. data/lib/dao/route.rb +1 -0
  52. data/lib/dao/slug.rb +12 -36
  53. data/lib/dao/status.rb +91 -7
  54. data/lib/dao/stdext.rb +1 -0
  55. data/lib/dao/support.rb +90 -80
  56. data/lib/dao/upload.rb +396 -0
  57. data/lib/dao/validations.rb +23 -5
  58. data/lib/dao/validations/callback.rb +5 -0
  59. data/lib/dao/validations/common.rb +100 -3
  60. data/lib/dao/validations/instance.rb +17 -0
  61. data/lib/dao/validations/validator.rb +192 -91
  62. data/test/active_model_conducer_lint_test.rb +1 -0
  63. data/test/api_test.rb +15 -0
  64. data/test/conducer_test.rb +608 -90
  65. data/test/data/han-solo.jpg +0 -0
  66. data/test/form_test.rb +1 -0
  67. data/test/helper.rb +1 -0
  68. data/test/leak.rb +1 -0
  69. data/test/support_test.rb +4 -1
  70. data/test/testing.rb +1 -0
  71. data/test/validations_test.rb +176 -30
  72. metadata +120 -131
  73. data/b.rb +0 -38
  74. data/lib/dao/conducer/crud.rb +0 -70
  75. data/lib/dao/current.rb +0 -66
  76. data/lib/dao/image_cache.rb +0 -193
  77. data/lib/dao/rails/lib/generators/dao/templates/conducer_controller.rb +0 -79
  78. data/test/db.yml +0 -9
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Dao::Error < ::StandardError; end
3
4
 
data/lib/dao/extractor.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Extractor < BlankSlate
3
4
  attr :target
data/lib/dao/form.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Form
3
4
  # for html generation
@@ -8,6 +9,14 @@ module Dao
8
9
  include Tagz.globally
9
10
  end
10
11
 
12
+ # builder stuff for compatibity with rails' form_for()
13
+ #
14
+ class Builder
15
+ def Builder.new(object_name, object, view, options, block)
16
+ form = Form.new(object)
17
+ end
18
+ end
19
+
11
20
  # class methods
12
21
  #
13
22
  class << Form
@@ -144,18 +153,18 @@ module Dao
144
153
  options = args.extract_options!.to_options!
145
154
  keys = args.flatten
146
155
 
147
- id = options.delete(:id) || id_for(keys)
148
- klass = class_for(keys, options.delete(:class))
149
- error = error_for(keys, options.delete(:error))
150
- target = options.delete(:for) || id_for(keys)
151
-
152
156
  content =
153
- if block.nil? and !options.has_key?(:content)
154
- titleize(keys.last)
157
+ if block.nil?
158
+ keys.map{|key| key.to_s.titleize}.join(' ')
155
159
  else
156
- block ? block.call() : options.delete(:content)
160
+ block ? block.call() : (options.delete(:content) || options.delete(:value))
157
161
  end
158
162
 
163
+ id = options.delete(:id) || id_for(keys + [:label])
164
+ klass = class_for(keys, options.delete(:class))
165
+ error = error_for(keys, options.delete(:error))
166
+ target = options.delete(:for) || id_for(keys)
167
+
159
168
  label_(options_for(options, :for => target, :class => klass, :id => id, :data_error => error)){ content }
160
169
  end
161
170
 
@@ -191,7 +200,7 @@ module Dao
191
200
  input_(options_for(options)){}
192
201
  end
193
202
 
194
- def button(*args)
203
+ def button(*args, &block)
195
204
  options = args.extract_options!.to_options!
196
205
  keys = args.flatten
197
206
 
@@ -211,6 +220,91 @@ module Dao
211
220
  button_(options_for(options, :type => type, :name => name, :value => value, :class => klass, :id => id, :data_error => error)){}
212
221
  end
213
222
 
223
+ def radio_button(*args, &block)
224
+ options = args.extract_options!.to_options!
225
+ keys = args.flatten
226
+
227
+ type = options.delete(:type) || :radio
228
+ name = options.delete(:name) || name_for(keys)
229
+ id = options.delete(:id) || id_for(keys)
230
+ klass = class_for(keys, options.delete(:class))
231
+ error = error_for(keys, options.delete(:error))
232
+
233
+ unless options.has_key?(:checked)
234
+ checked =
235
+ if options.has_key?(:value) and attributes.has?(keys)
236
+ a = attributes.get(keys)
237
+ b = options[:value]
238
+ a==b or a.to_s==b.to_s
239
+ else
240
+ false
241
+ end
242
+ options[:checked] = checked if checked
243
+ end
244
+
245
+ input_(options_for(options, :type => :radio, :name => name, :class => klass, :id => id, :data_error => error)){}
246
+ end
247
+
248
+ def checkbox(*args, &block)
249
+ options = args.extract_options!.to_options!
250
+ keys = args.flatten
251
+
252
+ type = options.delete(:type) || :checkbox
253
+ name = options.delete(:name) || name_for(keys)
254
+ id = options.delete(:id) || id_for(keys)
255
+ klass = class_for(keys, options.delete(:class))
256
+ error = error_for(keys, options.delete(:error))
257
+ values = options.delete(:values) || options.delete(:checked)
258
+
259
+ unless options.has_key?(:checked)
260
+ checked = !!attributes.get(keys)
261
+ options[:checked] = checked if checked
262
+ end
263
+
264
+ value_for =
265
+ case values
266
+ when false, nil
267
+ {true => '1', false => '0'}
268
+ when Hash
269
+ h = {}
270
+ values.map{|k, v| h[ k =~ /t|1|on|yes/ ? true : false ] = v}
271
+ h
272
+ else
273
+ t, f, *ignored = Array(values).flatten.compact
274
+ {true => t, false => f}
275
+ end
276
+ value_for[true] ||= '1'
277
+ value_for[false] ||= '0'
278
+
279
+ hidden_options =
280
+ options.dup.tap{|o| o.delete(:checked)}
281
+
282
+ tagz{
283
+ input_(options_for(hidden_options, :type => :hidden, :name => name, :value => value_for[false])){}
284
+
285
+ __
286
+
287
+ input_(
288
+ options_for(
289
+ options,
290
+ :type => :checkbox,
291
+ :name => name,
292
+ :value => value_for[true],
293
+ :class => klass,
294
+ :id => id,
295
+ :data_error => error
296
+ )
297
+ ){}
298
+ }
299
+ end
300
+
301
+ def hidden(*args, &block)
302
+ options = args.extract_options!.to_options!
303
+ options[:type] = :hidden
304
+ args.push(options)
305
+ input(*args, &block)
306
+ end
307
+
214
308
  def reset(*args)
215
309
  options = args.extract_options!.to_options!
216
310
  options[:type] = :reset
@@ -242,7 +336,7 @@ module Dao
242
336
  keys = args.flatten
243
337
 
244
338
  name = options.delete(:name) || name_for(keys)
245
- from = options.delete(:from) || options.delete(:options) || attributes.get(*keys)
339
+ from = options.delete(:from) || options.delete(:options)
246
340
  blank = options.delete(:blank)
247
341
 
248
342
  selected =
@@ -301,17 +395,19 @@ module Dao
301
395
 
302
396
  case returned
303
397
  when Array
304
- value, content, selected, *ignored = returned
398
+ content, value, selected, *ignored = returned
305
399
  when Hash
400
+ content = returned[:content]
306
401
  value = returned[:value]
307
- content = returned[:content] || value
308
402
  selected = returned[:selected]
309
403
  else
310
- value = returned
311
404
  content = returned
405
+ value = returned
312
406
  selected = nil
313
407
  end
314
408
 
409
+ value ||= content
410
+
315
411
  if selected.nil?
316
412
  selected = value.to_s==selected_value.to_s
317
413
  end
@@ -323,6 +419,31 @@ module Dao
323
419
  }
324
420
  end
325
421
 
422
+ def upload(*args, &block)
423
+ options = args.extract_options!.to_options!
424
+ keys = args.flatten
425
+
426
+ cache_key = keys + [:cache]
427
+ file_key = keys + [:file]
428
+
429
+ cache_name = options.delete(:cache_name) || name_for(cache_key)
430
+ file_name = options.delete(:file_name) || options.delete(:name) || name_for(file_key)
431
+
432
+ id = options.delete(:id) || id_for(keys)
433
+ klass = class_for(keys, options.delete(:class))
434
+ error = error_for(keys, options.delete(:error))
435
+
436
+ cache_value = attributes.get(cache_key)
437
+
438
+ tagz{
439
+ input_(:name => cache_name, :value => cache_value, :type => :hidden){ }
440
+
441
+ __
442
+
443
+ input_(options_for(options, :name => file_name, :class => klass, :id => id, :data_error => error, :type => :file)){ }
444
+ }
445
+ end
446
+
326
447
  # html generation support methods
327
448
  #
328
449
  def id_for(keys)
@@ -366,11 +487,32 @@ module Dao
366
487
  else
367
488
  value
368
489
  end
369
- Tagz.escapeHTML(value)
490
+ value.respond_to?(:html_safe) ? value : Tagz.escapeHTML(value)
491
+ end
492
+
493
+ def Form.prefix_for(name)
494
+ "dao[#{ name }]"
370
495
  end
371
496
 
372
497
  def Form.name_for(name, *keys)
373
- "dao[#{ name }][#{ Array(keys).flatten.compact.join('.') }]"
498
+ "#{ prefix_for(name) }[#{ key_for(*keys) }]"
499
+ end
500
+
501
+ def Form.key_for(*keys)
502
+ keys.flatten.compact.map do |key|
503
+ case
504
+ when Integer === key
505
+ key
506
+ when key =~ /^\d+$/
507
+ "~#{ key }"
508
+ else
509
+ key
510
+ end
511
+ end.join('.')
512
+ end
513
+
514
+ def key_for(*keys)
515
+ Form.key_for(name, *keys)
374
516
  end
375
517
 
376
518
  def name_for(*keys)
@@ -380,11 +522,28 @@ module Dao
380
522
  def options_for(*hashes)
381
523
  map = Map.new
382
524
  hashes.flatten.each do |h|
383
- h.each{|k,v| map[attr_for(k)] = v unless v.nil?}
525
+ case((data = h.delete(:data) || h.delete('data')))
526
+ when Hash
527
+ data.each{|k,v| map[data_attr_for(k)] = v unless v.nil?}
528
+ else
529
+ h[:data] = data
530
+ end
531
+
532
+ h.each do |k,v|
533
+ map[attr_for(k)] = v unless v.nil?
534
+ end
384
535
  end
385
536
  map
386
537
  end
387
538
 
539
+ def attr_for(string)
540
+ slug_for(string).gsub(/_/, '-')
541
+ end
542
+
543
+ def data_attr_for(string)
544
+ "data-#{ attr_for(string) }"
545
+ end
546
+
388
547
  def slug_for(string)
389
548
  string = string.to_s
390
549
  words = string.to_s.scan(%r/\w+/)
@@ -393,10 +552,6 @@ module Dao
393
552
  words.join('-').downcase.sub(/_+$/, '')
394
553
  end
395
554
 
396
- def attr_for(string)
397
- slug_for(string).gsub(/_/, '-')
398
- end
399
-
400
555
  def titleize(string)
401
556
  string = string.to_s
402
557
  string = string.titleize if string.respond_to?(:titleize)
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  module InstanceExec
3
4
  Code = proc do
data/lib/dao/mode.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Mode < ::String
3
4
  # class methods
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  begin
2
3
  MongoMapper
3
4
  rescue NameError
data/lib/dao/name.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Name < ::String
3
4
  def Name.for(name)
data/lib/dao/params.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Params < ::Map
3
4
  # mixins
@@ -36,7 +37,7 @@ module Dao
36
37
  # look good for inspect
37
38
  #
38
39
  def inspect
39
- ::JSON.pretty_generate(self, :max_nesting => 0)
40
+ Dao.json_for(self)
40
41
  end
41
42
 
42
43
  # support updates with dao-ish objects
data/lib/dao/path.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Path < ::String
3
4
  class Error < ::StandardError; end
@@ -0,0 +1,24 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Dao
3
+ class PathMap < ::Map
4
+ def to_json(*args, &block)
5
+ as_json.to_json(*args, &block)
6
+ end
7
+
8
+ def as_json
9
+ inject(Map.new){|json, kv| json.update(json_key_for(kv.first) => kv.last)}
10
+ end
11
+
12
+ def json_key_for(key)
13
+ Array(key).join('.').gsub(/\.(\d+)(\.)?/, '[\1]\2')
14
+ end
15
+ end
16
+ end
17
+
18
+
19
+ if $0 == __FILE__
20
+ pm = Dao::PathMap.new
21
+ pm[[:array, 0, :key]] = 'value'
22
+ pm[[:key]] = 'value'
23
+ p pm.as_json
24
+ end
data/lib/dao/rack.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  if defined?(Rack)
2
3
  Dao.load %w[ rack/middleware.rb ]
3
4
  end
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  module Middleware
3
4
  Dao.load %w[ rack/middleware/params_parser.rb ]
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  module Middleware
3
4
  class ParamsParser
data/lib/dao/rails.rb CHANGED
@@ -1,11 +1,12 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  if defined?(Rails)
2
3
 
3
4
  module Dao
4
5
  ## support unloadable
5
6
  #
6
- def Api.before_remove_const
7
- unload!
8
- end
7
+ #def Api.before_remove_const
8
+ #unload!
9
+ #end
9
10
 
10
11
  ##
11
12
  #
@@ -17,8 +18,7 @@ if defined?(Rails)
17
18
 
18
19
  paths.path = ROOT_DIR
19
20
 
20
- config.autoload_paths += %w( app/models app )
21
-
21
+ ### config.autoload_paths += %w( app/models app )
22
22
  ### config.autoload_paths << APP_DIR
23
23
  ### $LOAD_PATH.push(File.join(Rails.root.to_s, 'app'))
24
24
 
@@ -30,39 +30,19 @@ if defined?(Rails)
30
30
 
31
31
  # yes yes, this should probably be somewhere else...
32
32
  #
33
- config.after_initialize do
33
+ config.before_initialize do
34
34
 
35
35
  ActionController::Base.module_eval do
36
-
37
- before_filter do |controller|
38
- # set the dao controller
39
- #
40
- Dao.current_controller = controller
41
-
42
- # pre-parse any obvious dao params
43
- #
44
- controller.instance_eval do
45
- Dao.normalize_parameters(params)
46
- end
47
- end
48
-
49
- # you will likely want to override this!
36
+ # normalize dao params
50
37
  #
51
- def current_api
52
- @api ||= (
53
- api = Api.new
54
- %w( real_user effective_user current_user ).each do |attr|
55
- getter, setter = "#{ attr }", "#{ attr }="
56
- api.send(setter, send(getter)) if(respond_to?(getter) and api.respond_to?(setter))
57
- end
58
- api
59
- )
38
+ before_filter do |controller|
39
+ Dao.current_controller ||= controller
40
+ Dao.normalize_parameters(controller.send(:params))
60
41
  end
61
- helper_method(:current_api)
62
- alias_method(:api, :current_api)
63
- helper_method(:api)
64
42
 
65
43
  # setup sane rescuing from dao errors with crap statuses
44
+ #
45
+ # raise(Dao::Error::Result.new(result))
66
46
  #
67
47
  rescue_from(Dao::Error::Result) do |error|
68
48
  result = error.result