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 Api
3
4
  # class methods
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Context
3
4
  Attrs = %w(
@@ -42,6 +43,7 @@ module Dao
42
43
  @result = Result.new
43
44
  @result.path = @path
44
45
  @result.route = @route
46
+ @result.status = @status
45
47
  @result.mode = @api.mode
46
48
  @result.params = @params
47
49
  @result.errors = @params.errors
data/lib/dao/api/dsl.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Api
3
4
  class DSL < BlankSlate
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Api
3
4
  Initializers = {} unless defined?(Initializers)
data/lib/dao/api/modes.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Api
3
4
  class << Api
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Api
3
4
  class << Api
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class BlankSlate
3
4
  instance_methods.each{|m| undef_method(m) unless m.to_s =~ /(^__)|object_id/}
data/lib/dao/conducer.rb CHANGED
@@ -1,36 +1,37 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
-
3
- class Conducer
4
3
  ##
5
- #
6
- include ActiveModel::Naming
7
- #include ActiveModel::Conversion
8
-
9
- #extend ActiveModel::Translation
10
- #include ActiveModel::AttributeMethods
11
- #include ActiveModel::Serialization
12
- #include ActiveModel::Dirty
13
- #include ActiveModel::MassAssignmentSecurity
14
- #include ActiveModel::Observing
15
- #include ActiveModel::Serializers::JSON
16
- #include ActiveModel::Serializers::Xml
17
-
18
- #include ActiveModel::Validations
19
-
20
- extend ActiveModel::Callbacks
21
-
22
- define_model_callbacks(:save, :create, :update, :destroy)
23
- define_model_callbacks(:reset, :initialize, :find, :touch)
24
- include ActiveModel::Validations::Callbacks
4
+ #
5
+ Dao.load('conducer/attributes.rb')
6
+ Dao.load('conducer/collection.rb')
7
+ Dao.load('conducer/active_model.rb')
8
+ Dao.load('conducer/controller_support.rb')
9
+ Dao.load('conducer/callback_support.rb')
10
+ Dao.load('conducer/view_support.rb')
11
+ Dao.load('conducer/nav_support.rb')
25
12
 
26
13
  ##
27
14
  #
15
+ class Conducer
16
+ ##
17
+ #
28
18
  include Dao::Validations
29
- include Dao::Current
30
19
 
31
- ## class_methods
32
- #
20
+ ## class_methods
21
+ #
33
22
  class << Conducer
23
+ def inherited(other)
24
+ super
25
+ ensure
26
+ other.build_collection_class!
27
+ subclasses.push(other)
28
+ subclasses.uniq!
29
+ end
30
+
31
+ def subclasses
32
+ defined?(@@subclasses) ? @@subclasses : (@@subclasses = [])
33
+ end
34
+
34
35
  def name(*args)
35
36
  return send('name=', args.first) unless args.empty?
36
37
  @name ||= super
@@ -40,43 +41,16 @@ module Dao
40
41
  @name = name.to_s
41
42
  end
42
43
 
43
- def model_name(*args)
44
- return send('model_name=', args.first) unless args.empty?
45
- @model_name ||= default_model_name
46
- end
47
-
48
- def model_name=(model_name)
49
- @model_name = model_name_for(model_name)
50
- end
51
-
52
- def model_name_for(model_name)
53
- ActiveModel::Name.new(Map[:name, model_name])
54
- end
55
-
56
- def default_model_name
57
- model_name_for(name.to_s.sub(/Conducer$/, ''))
58
- end
59
-
60
- def table_name
61
- @table_name ||= model_name.plural.to_s
62
- end
63
- alias_method('collection_name', 'table_name')
64
-
65
- def table_name=(table_name)
66
- @table_name = table_name.to_s
67
- end
68
- alias_method('collection_name=', 'table_name=')
69
-
70
44
  def controller
71
- defined?(@controller) ? @controller : Dao.current_controller
45
+ Dao.current_controller || Dao.mock_controller
72
46
  end
73
47
 
74
48
  def controller=(controller)
75
- @controller = controller
49
+ Dao.current_controller = controller
76
50
  end
77
51
 
78
- def mock_controller(*args, &block)
79
- Dao.mock_controller(*args, &block)
52
+ def current
53
+ @current ||= (defined?(::Current) ? ::Current : Map.new)
80
54
  end
81
55
 
82
56
  def raise!(*args, &block)
@@ -93,324 +67,382 @@ module Dao
93
67
  end
94
68
  end
95
69
 
96
- ## contructor
97
- #
98
- %w(
99
- name
100
- attributes
101
- errors
102
- form
103
- ).each{|a| fattr(a)}
104
-
105
- def self.new(*args, &block)
70
+ ## crud-y lifecycle ctors
71
+ #
72
+ def Conducer.for(action, *args, &block)
106
73
  allocate.tap do |conducer|
107
- conducer.running_callbacks(:reset, :initialize) do
108
- conducer.send(:reset, *args, &block)
109
- conducer.send(:initialize, *args, &block)
110
- end
74
+ action = Action.new(action, conducer)
75
+ Dao.call(conducer, :init, action, *args, &block)
76
+ Dao.call(conducer, :initialize, *args, &block)
111
77
  end
112
78
  end
113
79
 
114
- def running_callbacks(*args, &block)
115
- which = args.shift
116
- if args.empty?
117
- run_callbacks(which, &block)
118
- else
119
- run_callbacks(which){ running_callbacks(*args, &block) }
80
+ def Conducer.call(*args, &block)
81
+ self.for(*args, &block)
82
+ end
83
+
84
+ %w( new create edit update destroy ).each do |action|
85
+ module_eval <<-__, __FILE__, __LINE__
86
+ def Conducer.for_#{ action }(*args, &block)
87
+ Conducer.for(#{ action.inspect }, *args, &block)
88
+ end
89
+ __
90
+ end
91
+
92
+ ## ctor
93
+ #
94
+ def Conducer.new(*args, &block)
95
+ allocate.tap do |conducer|
96
+ Dao.call(conducer, :init, *args, &block)
97
+ Dao.call(conducer, :initialize, *args, &block)
120
98
  end
121
99
  end
122
100
 
123
- def reset(*args, &block)
101
+ %w[
102
+ name
103
+ attributes
104
+ form
105
+ params
106
+ errors
107
+ status
108
+ models
109
+ model
110
+ conduces
111
+ ].each{|attr| fattr(attr)}
112
+
113
+ ## init runs *before* initialize - aka inside allocate
114
+ #
115
+ def init(*args, &block)
124
116
  controllers, args = args.partition{|arg| arg.is_a?(ActionController::Base)}
117
+ actions, args = args.partition{|arg| arg.is_a?(Action)}
118
+ models, args = args.partition{|arg| arg.respond_to?(:persisted?) }
125
119
  hashes, args = args.partition{|arg| arg.is_a?(Hash)}
126
120
 
127
- @name = self.class.model_name.singular
121
+ @name = self.class.model_name.singular.sub(/_+$/, '')
128
122
  @attributes = Attributes.for(self)
129
123
  @form = Form.for(self)
124
+ @params = Map.new
130
125
 
131
- validator.reset
126
+ @errors = validator.errors
127
+ @status = validator.status
132
128
 
133
129
  set_controller(controllers.shift || Dao.current_controller || Dao.mock_controller)
134
130
 
135
- hashes.each do |hash|
136
- hash.each do |key, val|
137
- @attributes.set(key_for(key) => val)
138
- end
139
- end
131
+ set_action(actions.shift) unless actions.empty?
140
132
 
141
- self
133
+ set_models(models)
134
+
135
+ set_mounts(self.class.mounted)
136
+
137
+ update_params(hashes)
138
+
139
+ @default_initialize = nil
142
140
  end
143
141
 
144
- def errors
145
- validator.errors
142
+ def set_models(*models)
143
+ @models =
144
+ models.flatten.compact
145
+
146
+ candidates =
147
+ @models.select{|model| model.class.model_name == self.class.model_name}
148
+
149
+ @model =
150
+ case candidates.size == 1
151
+ when 1
152
+ candidates.first
153
+ else
154
+ @models.first
155
+ end
156
+
157
+ @models.each do |model|
158
+ key = model_key_for(model)
159
+ ivar = "@#{ key }"
160
+ instance_variable_set(ivar, model) unless instance_variable_defined?(ivar)
161
+ end
146
162
  end
147
163
 
148
- def status
149
- validator.status
164
+ def update_params(*hashes)
165
+ hashes.flatten.compact.each{|hash| @params.apply(hash)}
150
166
  end
151
167
 
168
+ ## a sane initialize is provided for you. you are free to override it
169
+ # *** without *** calling super
170
+ #
152
171
  def initialize(*args, &block)
172
+ initialize_for_action(*args, &block)
173
+ update_models(models) unless models.empty?
174
+ update_attributes(params) unless params.empty?
153
175
  end
154
176
 
155
- ## instance_methods
156
- #
157
- def inspect
158
- ::JSON.pretty_generate(@attributes, :max_nesting => 0)
177
+ def set_mounts(list)
178
+ list.each do |args, block|
179
+ mount(*args, &block)
180
+ end
159
181
  end
160
182
 
161
- def id
162
- @attributes[:id] || @attributes[:_id]
183
+ def model_key_for(model)
184
+ case model
185
+ when String
186
+ model
187
+ else
188
+ model.class.name
189
+ end.demodulize.underscore
163
190
  end
164
191
 
165
- def id=(id)
166
- @attributes[:id] = id
192
+ def initialize_for_action(*args, &block)
193
+ @action.call(:initialize, *args, &block)
167
194
  end
168
195
 
169
- def key_for(*keys)
170
- keys.flatten.map{|key| key =~ %r/^\d+$/ ? Integer(key) : key}
171
- #key = keys.flatten.join('.').strip
172
- #key.split(%r/\s*[,.]\s*/).map{|key| key =~ %r/^\d+$/ ? Integer(key) : key}
196
+ def conduces(*args)
197
+ if args.empty?
198
+ @model
199
+ else
200
+ @model = args.flatten.compact.first
201
+ @models.delete(@model)
202
+ @models.unshift(@model)
203
+ @model
204
+ end
173
205
  end
206
+ alias_method(:set_model, :conduces)
174
207
 
175
- def [](key)
176
- @attributes.get(key_for(key))
208
+ def conduces=(model)
209
+ conduces(model)
177
210
  end
178
211
 
179
- def []=(key, val)
180
- @attributes.set(key_for(key), val)
212
+ def conduces?(model)
213
+ conduces == model
181
214
  end
182
215
 
183
- %w( set get has? update ).each do |m|
184
- module_eval <<-__, __FILE__, __LINE__
185
- def #{ m }(*a, &b)
186
- @attributes.#{ m }(*a, &b)
216
+ def update_models(*models)
217
+ models.flatten.compact.each do |model|
218
+ if conduces?(model)
219
+ update_attributes(model.attributes)
220
+ else
221
+ update_attributes(model_key_for(model), model.attributes)
187
222
  end
188
- __
223
+ end
189
224
  end
190
225
 
191
- def method_missing(method, *args, &block)
192
- case method.to_s
193
- when /^(.*)[=]$/
194
- key = key_for($1)
195
- val = args.first
196
- @attributes.set(key => val)
197
-
198
- when /^(.*)[!]$/
199
- key = key_for($1)
200
- val = true
201
- @attributes.set(key => val)
226
+ def update_attributes(*args, &block)
227
+ attributes =
228
+ case
229
+ when args.size == 1 && args.first.is_a?(Hash)
230
+ args.first
231
+ else
232
+ if args.size >= 2
233
+ val = args.pop
234
+ key = args.flatten.compact
235
+ {key => val}
236
+ else
237
+ {}
238
+ end
239
+ end
202
240
 
203
- when /^(.*)[?]$/
204
- key = key_for($1)
205
- @attributes.has?(key)
241
+ @attributes.set(attributes)
206
242
 
207
- else
208
- key = key_for(method)
209
- return @attributes.get(key) if @attributes.has?(key)
210
- super
211
- end
212
- end
243
+ update_mounted_attributes!
213
244
 
214
- def inspect
215
- "#{ self.class.name }(#{ @attributes.inspect.chomp })"
245
+ @attributes
216
246
  end
217
247
 
218
- # active_model support
219
- #
220
-
248
+ def update_mounted_attributes!
249
+ deepest_mounts_first = mounted.sort_by{|mnt| mnt._key.size}.reverse
221
250
 
222
- ## include ActiveModel::Conversion
223
- #
224
- def to_model
225
- self
251
+ deepest_mounts_first.each do |mount|
252
+ value = @attributes.get(mount._key)
253
+ mount._set(value) if mount.respond_to?(:_set)
254
+ @attributes.set(mount._key => mount)
255
+ end
226
256
  end
227
257
 
228
- def to_key
229
- id ? [id] : nil
258
+ def update_attributes!(*args, &block)
259
+ update_attributes(*args, &block)
260
+ ensure
261
+ save!
230
262
  end
231
263
 
232
- def to_param
233
- persisted? ? to_key.join('-') : nil
264
+ def attributes=(attributes)
265
+ @attributes.clear
266
+ update_attributes(attributes)
234
267
  end
235
268
 
236
- def persisted
237
- !!(defined?(@persisted) ? @persisted : id)
238
- end
239
- def persisted?
240
- persisted
241
- end
242
- def persisted=(value)
243
- @persisted = !!value
244
- end
245
- def persisted!
246
- self.persisted = true
269
+ def set(*args, &block)
270
+ update_attributes(*args, &block)
247
271
  end
248
272
 
249
- def new_record
250
- !!(defined?(@new_record) ? @new_record : id.blank?)
251
- end
252
- def new_record?
253
- new_record
273
+ def has?(*key)
274
+ key = key_for(key)
275
+ @attributes.has?(key)
254
276
  end
255
- def new_record=(value)
256
- @new_record = !!value
277
+
278
+ def get(*key)
279
+ key = key_for(key)
280
+ @attributes.get(key)
257
281
  end
258
- def new_record!
259
- self.new_record = true
282
+
283
+ def [](key)
284
+ get(key)
260
285
  end
261
286
 
262
- def destroyed
263
- !!(defined?(@destroyed) ? @destroyed : id.blank?)
287
+ def []=(key, val)
288
+ set(key, val)
264
289
  end
265
- def destroyed?
266
- destroyed
290
+
291
+ def method_missing(method, *args, &block)
292
+ re = /^([^=!?]+)([=!?])?$/imox
293
+
294
+ matched, key, suffix = re.match(method.to_s).to_a
295
+
296
+ case suffix
297
+ when '='
298
+ set(key, args.first)
299
+ when '!'
300
+ set(key, args.size > 0 ? args.first : true)
301
+ when '?'
302
+ has?(key)
303
+ else
304
+ case key
305
+ when /^current_(.*)/
306
+ Current.send($1)
307
+ else
308
+ has?(key) ? get(key) : super
309
+ end
310
+ end
267
311
  end
268
- def destroyed=(value)
269
- @destroyed = !!value
312
+
313
+ ## id support
314
+ #
315
+ def id(*args)
316
+ if args.blank?
317
+ @attributes[:_id] || @attributes[:id]
318
+ else
319
+ id = args.flatten.compact.shift
320
+ key = [:_id, :id].detect{|k| @attributes.has_key?(k)} || :id
321
+ @attributes[key] = id_for(id)
322
+ end
270
323
  end
271
- def destroyed!
272
- self.destroyed = true
324
+
325
+ def id?
326
+ self.id
273
327
  end
274
328
 
329
+ def id=(id)
330
+ self.id(id)
331
+ end
275
332
 
276
- ## extend ActiveModel::Translation
277
- #
278
- def self.human_attribute_name(attribute, options = {})
279
- attribute
333
+ def id!(id)
334
+ self.id(id)
280
335
  end
281
336
 
282
- def self.lookup_ancestors
283
- [self]
337
+ def id_for(object)
338
+ model?(object) ? object.id : object
284
339
  end
285
340
 
286
- def read_attribute_for_validation(key)
287
- self[key]
341
+ def model?(object)
342
+ object.respond_to?(:persisted?)
288
343
  end
289
344
 
290
- ## view support
291
- #
292
- url_helpers = Rails.application.try(:routes).try(:url_helpers)
293
- include(url_helpers) if url_helpers
294
- include(ActionView::Helpers) if defined?(ActionView::Helpers)
345
+ ## mixin controller support
346
+ #
347
+ module_eval(&ControllerSupport)
295
348
 
296
- def controller
297
- @controller ||= (Dao.current_controller || Dao.mock_controller)
298
- @controller
299
- end
349
+ ## mixin callback support
350
+ #
351
+ module_eval(&CallbackSupport)
300
352
 
301
- def controller=(controller)
302
- @controller = controller
303
- ensure
304
- default_url_options[:protocol] = @controller.request.protocol
305
- default_url_options[:host] = @controller.request.host
306
- default_url_options[:port] = @controller.request.port
307
- end
353
+ ## mixin view support
354
+ #
355
+ module_eval(&ViewSupport)
308
356
 
309
- def set_controller(controller)
310
- self.controller = controller
357
+ ##
358
+ #
359
+ def save
360
+ default_save
311
361
  end
312
362
 
313
- controller_delegates = %w(
314
- render
315
- render_to_string
316
- )
363
+ def default_save
364
+ return false unless valid?
317
365
 
318
- controller_delegates.each do |method|
319
- module_eval <<-__, __FILE__, __LINE__
320
- def #{ method }(*args, &block)
321
- controller.#{ method }(*args, &block)
366
+ if @model
367
+ attributes = self.attributes.dup
368
+
369
+ @models.each do |model|
370
+ next if model == @model
371
+ key = model_key_for(model)
372
+ attributes.delete(key)
322
373
  end
323
- __
324
- end
325
374
 
326
- ## generic crud support assuming valid .all, .find, #save and #destroy
327
- #
328
- =begin
329
- def self.create(*args, &block)
330
- allocate.tap do |conducer|
331
- conducer.running_callbacks :reset, :initialize, :create do
332
- conducer.send(:reset, *args, &block)
333
- conducer.send(:initialize, *args, &block)
334
- return false unless conducer.save
375
+ mounted.each do |mnt|
376
+ attributes.set(mnt._key, mnt._value)
335
377
  end
336
- end
337
- end
338
378
 
339
- def self.create!(*args, &block)
340
- allocate.tap do |conducer|
341
- conducer.running_callbacks :reset, :initialize, :create do
342
- conducer.send(:reset, *args, &block)
343
- conducer.send(:initialize, *args, &block)
344
- raise!(:validation_error) unless conducer.save
379
+ @model.update_attributes(attributes)
380
+
381
+ if @model.save
382
+ mounted.each{|mnt| mnt._clear}
383
+ return true
384
+ else
385
+ errors.relay(@model.errors)
386
+ return false
345
387
  end
388
+ else
389
+ raise NotImplementedError
346
390
  end
347
391
  end
348
-
349
- def self.blank(params = {})
350
- new
392
+
393
+ def save!
394
+ raise!(:validation_error, errors) unless !!save
395
+ true
351
396
  end
352
397
 
353
- def self.build(params = {})
354
- new
398
+ def destroy
399
+ if @model and @model.destroy
400
+ return true
401
+ else
402
+ raise NotImplementedError
403
+ end
355
404
  end
356
405
 
357
- def self.show(id)
358
- find(id)
406
+ def destroy!
407
+ raise!(:deletion_error) unless !!destroy
408
+ true
359
409
  end
360
410
 
361
- def self.index(params = {})
362
- all(params)
411
+ ## misc
412
+ #
413
+ def mount(object, *args, &block)
414
+ mounted = object.mount(self, *args, &block)
415
+ ensure
416
+ if mounted
417
+ Dao.ensure_interface!(mounted, :_set, :_key, :_value, :_clear)
418
+ self.mounted.push(mounted)
419
+ end
363
420
  end
364
421
 
365
- def self.edit(id)
366
- find(id)
422
+ def mounted
423
+ @mounted ||= []
367
424
  end
368
425
 
369
- def self.update(id)
370
- find(id)
426
+ def self.mount(*args, &block)
427
+ mounted.push([args, block])
371
428
  end
372
429
 
373
- def self.destroy(id)
374
- find(id)
430
+ def self.mounted
431
+ @mounted ||= []
375
432
  end
376
- =end
377
433
 
378
- ##
379
- #
380
-
381
- ##
382
- #
383
- def reload
384
- attributes =
385
- if id
386
- conducer = self.class.find(id)
387
- conducer ? conducer.attributes : {}
388
- else
389
- {}
390
- end
391
- reset(attributes)
392
- self
434
+ def key_for(key)
435
+ Dao.key_for(key)
393
436
  end
394
437
 
395
- def save!
396
- saved = !!save
397
- raise!(:validation_error) unless saved
398
- true
399
- end
400
-
401
- def update_attributes(attributes = {})
402
- @attributes.set(attributes)
403
- @attributes
438
+ def errors
439
+ validator.errors
404
440
  end
405
441
 
406
- def update_attributes!(*args, &block)
407
- update_attributes(*args, &block)
408
- ensure
409
- save!
442
+ def status
443
+ validator.status
410
444
  end
411
445
 
412
- ## misc
413
- #
414
446
  def model_name
415
447
  self.class.model_name
416
448
  end
@@ -419,19 +451,28 @@ module Dao
419
451
  @form
420
452
  end
421
453
 
454
+ def helper
455
+ @helper ||= ::Helper.new
456
+ end
457
+
422
458
  def raise!(*args, &block)
423
459
  self.class.raise!(*args, &block)
424
460
  end
425
461
 
426
- def as_json
462
+ def as_json(*args, &block)
427
463
  @attributes
428
464
  end
429
465
 
430
466
  def conducer
431
467
  self
432
468
  end
433
- end
434
469
 
435
- Dao.load('conducer/attributes.rb')
436
- Dao.load('conducer/crud.rb')
470
+ def inspect
471
+ "#{ self.class.name }(#{ @attributes.inspect.chomp })"
472
+ end
473
+
474
+ def to_s
475
+ inspect
476
+ end
477
+ end
437
478
  end