dao 4.4.4 → 4.6.4

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.
@@ -35,7 +35,14 @@ module Dao
35
35
 
36
36
  def default_model_name
37
37
  return model_name_for('Conducer') if self == Dao::Conducer
38
- model_name_for(name.to_s.sub(/Conducer$/, '').sub(/(:|_)+$/, ''))
38
+
39
+ suffixes = /(Conducer|Resource|Importer|Presenter|Conductor|Cell)\Z/o
40
+
41
+ name = self.name.to_s
42
+ name.sub!(suffixes, '') unless name.sub(suffixes, '').blank?
43
+ name.sub!(/(:|_)+$/, '')
44
+
45
+ model_name_for(name)
39
46
  end
40
47
 
41
48
  def collection_name
@@ -13,6 +13,10 @@ module Dao
13
13
  def collection_for(models, *args, &block)
14
14
  collection_class.load(models, *args, &block)
15
15
  end
16
+
17
+ def collection
18
+ collection_class
19
+ end
16
20
  end
17
21
 
18
22
  class Collection < ::Array
@@ -18,10 +18,14 @@ module Dao
18
18
  def set_controller(controller)
19
19
  @controller = controller
20
20
  ensure
21
- default_url_options[:protocol] = @controller.request.protocol
22
- default_url_options[:host] = @controller.request.host
23
- default_url_options[:port] = @controller.request.port
24
- @action = Action.new(@controller.send(:action_name).to_s, self)
21
+ if defined?(default_url_options)
22
+ [:protocol, :host, :port].each{|attr| default_url_options[attr] = @controller.request.send(attr)}
23
+ end
24
+ @action = Action.new((@controller.send(:action_name) || :index).to_s, self)
25
+ end
26
+
27
+ def request
28
+ @controller.send(:request) if @controller
25
29
  end
26
30
 
27
31
  ##
@@ -2,9 +2,10 @@
2
2
  module Dao
3
3
  class Conducer
4
4
  def nav_for(*args, &block)
5
- Nav.new(*args, &block).for(controller)
5
+ Nav.build(*args, &block)
6
6
  end
7
7
  alias_method(:nav, :nav_for)
8
8
  alias_method(:navigation, :nav_for)
9
+ alias_method(:navigation_for, :nav_for)
9
10
  end
10
11
  end
@@ -6,11 +6,15 @@ module Dao
6
6
 
7
7
  class << Conducer
8
8
  include Tagz.globally
9
- end
10
9
 
11
- url_helpers = Rails.application.try(:routes).try(:url_helpers)
12
- include(url_helpers) if url_helpers
13
- include(ActionView::Helpers) if defined?(ActionView::Helpers)
10
+ def install_routes!
11
+ url_helpers = Rails.application.try(:routes).try(:url_helpers)
12
+ include(url_helpers) if url_helpers
13
+ include(ActionView::Helpers) if defined?(ActionView::Helpers)
14
+ extend(url_helpers) if url_helpers
15
+ extend(ActionView::Helpers) if defined?(ActionView::Helpers)
16
+ end
17
+ end
14
18
  end
15
19
  end
16
20
  end
data/lib/dao/errors.rb CHANGED
@@ -113,31 +113,21 @@ module Dao
113
113
  alias_method('add_to_base', 'add')
114
114
  alias_method('add_to_base!', 'add!')
115
115
 
116
- def relay(other, options = {})
117
- case
118
- when other.respond_to?(:each)
119
- other.each do |key, messages|
120
- Array(messages).each do |message|
121
- add(key, message, options = {})
122
- end
123
- end
124
- when other.respond_to?(:each_pair)
125
- other.each_pair do |key, messages|
126
- Array(messages).each do |message|
127
- add(key, message, options = {})
128
- end
129
- end
116
+ def relay(*args)
117
+ options = args.size > 1 ? Map.options_for!(args) : Map.new
130
118
 
131
- when other.respond_to?(:each_slice)
132
- Array(other).flatten.each_slice(2) do |key, messages|
133
- Array(messages).each do |message|
134
- add(key, message, options = {})
135
- end
136
- end
119
+ prefix = Array(options.delete(:prefix))
137
120
 
138
- else
139
- raise(ArgumentError, other.class.name)
121
+ args.flatten.compact.each do |source|
122
+ errors = source.respond_to?(:errors) ? source.errors : source
123
+
124
+ errors.each do |*argv|
125
+ msgs = Array(argv.pop)
126
+ key = prefix + Array(argv.pop)
127
+ msgs.each{|msg| add(Array(options[:key] || key), msg, options)}
128
+ end
140
129
  end
130
+
141
131
  self
142
132
  end
143
133
 
@@ -181,7 +171,9 @@ module Dao
181
171
  index = keys.pop
182
172
  key = keys
183
173
  value = value.to_s
174
+
184
175
  next if value.strip.empty?
176
+
185
177
  if key == Global
186
178
  global_messages.push([key, value])
187
179
  else
@@ -200,6 +192,18 @@ module Dao
200
192
  end
201
193
  end
202
194
 
195
+ def flatten
196
+ hash = Hash.new
197
+
198
+ depth_first_each do |keys, value|
199
+ index = keys.pop
200
+ hash[keys] ||= []
201
+ hash[keys].push("#{ value }")
202
+ end
203
+
204
+ hash
205
+ end
206
+
203
207
  def each_full_message
204
208
  full_messages.each{|msg| yield msg}
205
209
  end
@@ -212,6 +216,14 @@ module Dao
212
216
  select{|message| not message.strip.empty?}
213
217
  end
214
218
 
219
+ def global
220
+ reject{|k, v| k != Global}
221
+ end
222
+
223
+ def local
224
+ reject{|k, v| k == Global}
225
+ end
226
+
215
227
  # html generation methods
216
228
  #
217
229
  def to_html(*args)
@@ -222,50 +234,104 @@ module Dao
222
234
  if block
223
235
  define_method(:to_html, &block)
224
236
  else
225
- default_errors_to_html(*args)
237
+ errors_to_html(*args)
226
238
  end
227
239
  end
228
240
 
229
- def Errors.default_errors_to_html(*args)
241
+ def Errors.errors_to_html(*args)
242
+ ::Errors2Html.to_html(*args)
243
+ end
244
+
245
+ def to_s(format = :html, *args, &block)
246
+ case format.to_s
247
+ when /html/
248
+ to_html(*args, &block)
249
+
250
+ when /text/
251
+ to_text(*args, &block)
252
+ end
253
+ end
254
+
255
+ class KeyPrefixer
256
+ attr_accessor :object
257
+ attr_accessor :prefix
258
+ attr_accessor :global
259
+
260
+ def initialize(object)
261
+ @object = object
262
+
263
+ @prefix =
264
+ if @object && @object.respond_to?(:model_name)
265
+ @object.model_name.underscore
266
+ else
267
+ nil
268
+ end
269
+
270
+ @global = Array(Global)
271
+ end
272
+
273
+ def prefix(key)
274
+ is_global_key = key == @global || Array(key) == @global
275
+
276
+ if @prefix
277
+ if is_global_key
278
+ @prefix
279
+ else
280
+ ["#{ @prefix }.#{ key[0] }", *key[1..-1]]
281
+ end
282
+ else
283
+ if is_global_key
284
+ 'global'
285
+ else
286
+ key
287
+ end
288
+ end
289
+ end
290
+ end
291
+
292
+ def key_prefixer
293
+ @key_prefixer ||= KeyPrefixer.new(object)
294
+ end
295
+
296
+ def prefix_key(key)
297
+ key_prefixer.prefix(key)
298
+ end
299
+
300
+ def Errors.to_hash(*args)
230
301
  error = args.shift
231
302
  options = Map.options_for!(args)
232
303
  errors = [error, *args].flatten.compact
233
304
 
234
- at_least_one_error = false
235
-
236
- emap = Map.new
305
+ map = Map.new
237
306
 
238
307
  errors.each do |e|
239
308
  e.full_messages.each do |key, message|
240
- at_least_one_error = true
241
- emap[key] ||= message
309
+ k = e.key_prefixer.prefix(key)
310
+
311
+ map.set(k, []) unless map.has?(k)
312
+ map.get(k).push("#{ message }")
242
313
  end
243
314
  end
244
315
 
245
- return "" unless at_least_one_error
246
-
247
- div_(:class => "dao errors summary"){
248
- __
249
-
250
- h3_(:class => "caption"){ "We're so sorry, but can you please fix the following errors?" }
251
- __
316
+ map.to_hash
317
+ end
252
318
 
253
- dl_(:class => "list"){
254
- emap.each do |key, message|
255
- title = Array(key).join(" ").titleize
319
+ def to_hash
320
+ Errors.to_hash(self)
321
+ end
256
322
 
257
- type = Array(key) == Array(Global) ? "global" : "field"
323
+ def Errors.errors_to_text(*args)
324
+ hash = to_hash(*args)
258
325
 
259
- dt_(:class => "title #{ type }"){ title }
260
- dd_(:class => "message #{ type }"){ message }
261
- end
262
- }
263
- __
264
- }
326
+ if hash.empty?
327
+ nil
328
+ else
329
+ hash.to_yaml
330
+ end
265
331
  end
266
332
 
267
- def to_s(*args, &block)
268
- to_html(*args, &block)
333
+ def to_text
334
+ Errors.errors_to_text(self)
269
335
  end
270
336
  end
271
337
  end
data/lib/dao/form.rb CHANGED
@@ -11,9 +11,20 @@ module Dao
11
11
 
12
12
  # builder stuff for compatibity with rails' form_for()
13
13
  #
14
- class Builder
14
+ class Builder < Form
15
15
  def Builder.new(object_name, object, view, options, block)
16
- form = Form.new(object)
16
+ if object.respond_to?(:form)
17
+
18
+ html = options[:html] || {}
19
+ html[:class] ||= 'dao'
20
+ unless html[:class] =~ /(\s|\A)dao(\Z|\s)/o
21
+ html[:class] << ' dao dao-form'
22
+ end
23
+
24
+ object.form
25
+ else
26
+ raise ArgumentError, object.class.name
27
+ end
17
28
  end
18
29
  end
19
30
 
@@ -69,14 +80,17 @@ module Dao
69
80
 
70
81
  fattr(:name) do
71
82
  name =
72
- catch(:name) do
73
- if @object.respond_to?(:name)
74
- throw :name, @object.name
75
- end
76
- if @object.instance_variable_defined?('@name')
77
- throw :name, @object.instance_variable_get('@name')
78
- end
79
- 'form'
83
+ case
84
+ when @object.respond_to?(:form_name)
85
+ @object.form_name
86
+ when @object.respond_to?(:name)
87
+ @object.name
88
+ when @object.instance_variable_defined?('@form_name')
89
+ @object.instance_variable_get('@form_name')
90
+ when @object.instance_variable_defined?('@name')
91
+ @object.instance_variable_get('@name')
92
+ else
93
+ :form
80
94
  end
81
95
 
82
96
  case name
@@ -107,28 +121,24 @@ module Dao
107
121
  end
108
122
  end
109
123
 
110
- fattr(:status) do
111
- status =
112
- catch(:status) do
113
- if @object.respond_to?(:status)
114
- throw :status, @object.status
115
- end
116
- if @object.instance_variable_defined?('@status')
117
- throw :status, @object.instance_variable_get('@status')
118
- end
119
- Status.new
120
- end
124
+ # support for rails' forms...
125
+ #
126
+ fattr(:multipart){ true }
121
127
 
122
- case status
123
- when Status
124
- status
125
- else
126
- raise(ArgumentError.new("#{ status.inspect } (#{ status.class })"))
127
- end
128
+ %w( [] []= get set has has? ).each do |method|
129
+ class_eval <<-__
130
+ def #{ method }(*args, &block)
131
+ attributes.#{ method }(*args, &block)
132
+ end
133
+ __
128
134
  end
129
135
 
130
136
  # html generation methods
131
137
  #
138
+ def element(which, *args, &block)
139
+ send(which, *args, &block)
140
+ end
141
+
132
142
  def form(*args, &block)
133
143
  options = args.extract_options!.to_options!
134
144
  keys = args.flatten
@@ -153,11 +163,11 @@ module Dao
153
163
  options = args.extract_options!.to_options!
154
164
  keys = args.flatten
155
165
 
156
- content =
157
- if block.nil?
166
+ block ||=
167
+ proc do
168
+ options.delete(:content) ||
169
+ options.delete(:value) ||
158
170
  keys.map{|key| key.to_s.titleize}.join(' ')
159
- else
160
- block ? block.call() : (options.delete(:content) || options.delete(:value))
161
171
  end
162
172
 
163
173
  id = options.delete(:id) || id_for(keys + [:label])
@@ -165,7 +175,7 @@ module Dao
165
175
  error = error_for(keys, options.delete(:error))
166
176
  target = options.delete(:for) || id_for(keys)
167
177
 
168
- label_(options_for(options, :for => target, :class => klass, :id => id, :data_error => error)){ content }
178
+ label_(options_for(options, :for => target, :class => klass, :id => id, :data_error => error), &block)
169
179
  end
170
180
 
171
181
  def input(*args, &block)
@@ -210,14 +220,11 @@ module Dao
210
220
  klass = class_for(keys, options.delete(:class))
211
221
  error = error_for(keys, options.delete(:error))
212
222
 
213
- value =
214
- if block.nil? and !options.has_key?(:value)
215
- value_for(attributes, keys)
216
- else
217
- block ? block.call(attributes.get(keys)) : options.delete(:value)
218
- end
223
+ value = options.has_key?(:value) ? options.delete(:value) : value_for(attributes, keys)
224
+
225
+ content = (block ? block.call : (options.delete(:content) || 'Submit'))
219
226
 
220
- button_(options_for(options, :type => type, :name => name, :value => value, :class => klass, :id => id, :data_error => error)){}
227
+ button_(options_for(options, :type => type, :name => name, :value => value, :class => klass, :id => id, :data_error => error)){ content }
221
228
  end
222
229
 
223
230
  def radio_button(*args, &block)
@@ -257,7 +264,7 @@ module Dao
257
264
  values = options.delete(:values) || options.delete(:checked)
258
265
 
259
266
  unless options.has_key?(:checked)
260
- checked = !!attributes.get(keys)
267
+ checked = Coerce.boolean(attributes.get(keys))
261
268
  options[:checked] = checked if checked
262
269
  end
263
270
 
@@ -336,29 +343,22 @@ module Dao
336
343
  keys = args.flatten
337
344
 
338
345
  name = options.delete(:name) || name_for(keys)
339
- from = options.delete(:from) || options.delete(:options)
340
- blank = options.delete(:blank)
346
+ values = options.delete(:values) || options.delete(:options) || options.delete(:from)
341
347
 
342
- selected =
343
- if options.has_key?(:selected)
344
- options.delete(:selected)
345
- else
346
- value_for(attributes, keys)
347
- end
348
+ has_blank = options.has_key?(:blank) && options[:blank] != false
349
+ blank = options.delete(:blank)
348
350
 
349
351
  id = options.delete(:id) || id_for(keys)
350
352
  klass = class_for(keys, options.delete(:class))
351
353
  error = error_for(keys, options.delete(:error))
352
354
 
353
- block ||= lambda{|pair| pair = Array(pair).flatten.compact; [pair.first, pair.last, selected=nil]}
354
-
355
- if from.nil?
355
+ if values.nil?
356
356
  key = keys.map{|key| "#{ key }"}
357
357
  key.last << "_options"
358
- from = attributes.get(*key) if attributes.has?(*key)
358
+ values = attributes.get(*key) if attributes.has?(*key)
359
359
  end
360
360
 
361
- list = Array(from)
361
+ list = Array(values).map{|value| value.dup rescue value} # ensure list is dup'd
362
362
 
363
363
  case list.first
364
364
  when Hash, Array
@@ -369,52 +369,68 @@ module Dao
369
369
  list.map!{|element| [element, element]}
370
370
  end
371
371
 
372
- case blank
373
- when nil, false
374
- nil
375
- when true
376
- list.push(nil)
377
- else
378
- list.unshift(blank)
372
+ if has_blank
373
+ case blank
374
+ when false
375
+ blank = nil
376
+ when nil, true
377
+ blank = [nil, nil]
378
+ else
379
+ blank = [Array(blank).first, '']
380
+ end
379
381
  end
380
382
 
381
383
  selected_value =
382
- case selected
383
- when Array
384
- selected.first
385
- when Hash
386
- key = [:id, 'id', :value, 'value'].detect{|k| selected.has_key?(k)}
387
- key ? selected[key] : selected
388
- else
389
- selected
384
+ if options.has_key?(:selected)
385
+ options.delete(:selected)
386
+ else
387
+ value_for(attributes, keys)
390
388
  end
391
389
 
392
390
  select_(options_for(options, :name => name, :class => klass, :id => id, :data_error => error)){
393
- list.each do |pair|
394
- returned = block.call(pair)
395
-
396
- case returned
397
- when Array
398
- content, value, selected, *ignored = returned
399
- when Hash
400
- content = returned[:content]
401
- value = returned[:value]
402
- selected = returned[:selected]
403
- else
404
- content = returned
405
- value = returned
406
- selected = nil
407
- end
408
-
409
- value ||= content
391
+ if blank
392
+ content = blank.first || ''
393
+ value = blank.last
394
+ value.nil? ? option_(){ content } : option_(:value => value){ content }
395
+ end
410
396
 
411
- if selected.nil?
412
- selected = value.to_s==selected_value.to_s
397
+ unless list.empty?
398
+ list.each do |pair|
399
+ returned = block ? Dao.call(block, :call, pair.first, pair.last, selected_value) : pair
400
+
401
+ opts = Map.new
402
+ selected = nil
403
+
404
+ case returned
405
+ when Array
406
+ content, value, selected, *ignored = returned
407
+ if value.is_a?(Hash)
408
+ map = Map.for(value)
409
+ value = map.delete(:value)
410
+ selected = map.delete(:selected)
411
+ opts.update(map)
412
+ end
413
+
414
+ when Hash
415
+ content = returned[:content]
416
+ value = returned[:value]
417
+ selected = returned[:selected]
418
+
419
+ else
420
+ content = returned
421
+ value = returned
422
+ selected = nil
423
+ end
424
+
425
+ if selected.nil?
426
+ selected = (value.to_s == selected_value.to_s)
427
+ end
428
+
429
+ opts[:value] = (value.nil? ? content : value)
430
+ opts[:selected] = Coerce.boolean(selected) if selected
431
+
432
+ option_(opts){ content }
413
433
  end
414
-
415
- opts = {:value => value}
416
- opts[:selected] = !!selected if selected
417
- option_(opts){ content }
418
434
  end
419
435
  }
420
436
  end
@@ -521,6 +537,7 @@ module Dao
521
537
 
522
538
  def options_for(*hashes)
523
539
  map = Map.new
540
+
524
541
  hashes.flatten.each do |h|
525
542
  case((data = h.delete(:data) || h.delete('data')))
526
543
  when Hash
@@ -533,6 +550,11 @@ module Dao
533
550
  map[attr_for(k)] = v unless v.nil?
534
551
  end
535
552
  end
553
+
554
+ %w( readonly disabled autofocus checked multiple ).each do |attr|
555
+ map.delete(attr) unless Coerce.boolean(map[attr])
556
+ end
557
+
536
558
  map
537
559
  end
538
560