dao 4.4.4 → 4.6.4

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