dao 4.2.1 → 4.4.2

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