dao 4.4.4 → 4.6.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/dao/rails.rb CHANGED
@@ -27,6 +27,10 @@ if defined?(Rails)
27
27
  #initializer "dao.middleware" do |app|
28
28
  #app.middleware.use Dao::Middleware::ParamsParser
29
29
  #end
30
+
31
+ config.after_initialize do
32
+ Dao::Conducer.install_routes!
33
+ end
30
34
 
31
35
  # yes yes, this should probably be somewhere else...
32
36
  #
@@ -1,28 +1,18 @@
1
- /* dao errors */
1
+ /* dao form errors */
2
2
 
3
- .dao.errors {
4
- font-weight: normal;
3
+ .errors-summary {
4
+ box-sizing: border-box;
5
5
  width: 100%;
6
- border-bottom: 1px solid #ccc;
7
- background-color: #ffe;
8
- padding: 0.5em;
6
+ height: auto;
7
+ color: #666;
8
+ background-color: #fffff6;
9
+ padding: 1em;
9
10
  }
10
-
11
- .dao.errors .caption {
11
+ .errors-caption {
12
12
  font-weight: bold;
13
- color: #333;
14
- font-style: italic;
15
- text-align: left;
16
- margin-bottom: 0.5em;
17
13
  }
18
-
19
- .dao.errors .title {
20
- padding-left: 1em;
21
- color: #666;
14
+ .errors-title {
22
15
  }
23
-
24
- .dao.errors .message {
25
- font-style: italic;
26
- font-weight: bold;
27
- width: 100%;
16
+ .errors-message {
28
17
  }
18
+
@@ -1,52 +1,27 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module DaoHelper
3
3
  def dao_form_for(*args, &block)
4
- options = args.extract_options!.to_options!
5
-
6
- model = args.flatten.detect{|arg| arg.respond_to?(:persisted?)}
7
-
8
- if model
9
- first = args.shift
10
- url = args.shift || options.delete(:url)
4
+ model = args.flatten.select{|arg| arg.respond_to?(:persisted?)}.last
11
5
 
12
- method = options.delete(:method)
13
- html = dao_form_attrs(options)
14
-
15
- options.clear
6
+ options = args.extract_options!.to_options!
16
7
 
17
- if model.persisted?
18
- method ||= :put
19
- else
20
- method ||= :post
21
- end
8
+ options[:builder] = Dao::Form::Builder
22
9
 
23
- url =
24
- case method
25
- when :put
26
- url_for(:action => :update)
27
- when :post
28
- url_for(:action => :create)
29
- else
30
- './'
31
- end
10
+ if options[:post] or model.blank?
11
+ options[:url] ||= (options.delete(:post) || request.fullpath)
12
+ options[:method] ||= :post
13
+ end
32
14
 
33
- options[:url] = url
34
- options[:html] = html.dup.merge(:method => method)
35
- #options[:builder] = Dao::Form::Builder
15
+ args.push(options)
36
16
 
37
- args.push(model)
38
- args.push(options)
39
-
40
- form_for(*args) do
41
- block.call(model.form)
42
- end
43
- else
44
- args.push(request.fullpath) if args.empty?
45
- args.push(dao_form_attrs(options))
46
- form_tag(*args, &block)
17
+ if model.blank?
18
+ name = 'form'
19
+ model = Class.new(Dao::Conducer){ model_name(name) }.new(params[name])
20
+ args.unshift(model)
47
21
  end
48
- end
49
22
 
23
+ form_for(*args, &block)
24
+ end
50
25
  alias_method(:dao_form, :dao_form_for)
51
26
 
52
27
  def dao_form_attrs(*args)
@@ -92,11 +67,10 @@ module DaoHelper
92
67
 
93
68
  @dao = api.send(mode, path, params)
94
69
  @dao.route = request.fullpath
95
- #@dao.mode = mode
96
70
 
97
- #unless options[:error!] == false
98
- @dao.error! unless @dao.status.ok?
99
- #end
71
+ unless options[:error!] == false
72
+ @dao.error! unless(@dao.status =~ or @dao.status == 420)
73
+ end
100
74
 
101
75
  block ? block.call(@dao) : @dao
102
76
  end
data/lib/dao/route.rb CHANGED
@@ -20,7 +20,7 @@ module Dao
20
20
  def pattern_for(route)
21
21
  route = Path.absolute_path_for(route.to_s)
22
22
  re = route.gsub(%r{/:[^/]+}, '/([^/]+)')
23
- /#{ re }/ioux
23
+ /#{ re }/iux
24
24
  end
25
25
 
26
26
  def path_for(route, params = {})
@@ -59,7 +59,8 @@ module Dao
59
59
 
60
60
  def params_for(path)
61
61
  match = pattern.match(path).to_a
62
- if match
62
+
63
+ unless match.empty?
63
64
  map = Map.new
64
65
  ignored = match.shift
65
66
  @keys.each_with_index do |key, index|
@@ -79,7 +80,7 @@ module Dao
79
80
  def match(name)
80
81
  each do |route|
81
82
  match = route.match(name)
82
- return route if match
83
+ return route unless match.empty?
83
84
  end
84
85
  return nil
85
86
  end
data/lib/dao/upload.rb CHANGED
@@ -152,6 +152,13 @@ class Upload < ::Map
152
152
  end
153
153
  end
154
154
 
155
+ def path_for(arg)
156
+ [:original_path, :original_filename, :path, :filename, :pathname].
157
+ map{|msg| arg.send(msg).to_s if arg.respond_to?(msg)}.
158
+ compact.
159
+ first or raise("could not find path_for(#{ arg.inspect })")
160
+ end
161
+
155
162
  alias_method('mount', 'new')
156
163
  end
157
164
 
@@ -161,7 +168,7 @@ class Upload < ::Map
161
168
  attr_accessor :hidden_key
162
169
  attr_accessor :name
163
170
  attr_accessor :value
164
- attr_accessor :path
171
+ attr_reader :path
165
172
  attr_accessor :dirname
166
173
  attr_accessor :basename
167
174
  attr_accessor :io
@@ -192,6 +199,8 @@ class Upload < ::Map
192
199
  end
193
200
 
194
201
  def _set(value)
202
+ return unless value
203
+
195
204
  value =
196
205
  case
197
206
  when value.is_a?(Hash)
@@ -216,6 +225,8 @@ class Upload < ::Map
216
225
  url = @value ? File.join(Upload.url, @value) : @placeholder.url
217
226
 
218
227
  update(:file => @io, :cache => @value, :url => url)
228
+
229
+ set_path(Upload.path_for(@io)) rescue nil
219
230
  end
220
231
 
221
232
  def _key
@@ -280,7 +291,7 @@ class Upload < ::Map
280
291
  copied = false
281
292
 
282
293
  Upload.rewind(io) do
283
- src = io.path
294
+ src = Upload.path_for(io)
284
295
  dst = path
285
296
 
286
297
  strategies = [
@@ -305,15 +316,26 @@ class Upload < ::Map
305
316
  end
306
317
 
307
318
  def gcopen(path)
308
- @path = path
309
- @dirname, @basename = File.split(@path)
310
- @value = File.join(File.basename(@dirname), @basename).strip
319
+ set_path(path)
311
320
  @io = open(@path, 'rb')
312
321
  IOs[object_id] = @io.fileno
313
322
  ObjectSpace.define_finalizer(self, Upload.method(:finalizer).to_proc)
314
323
  @io
315
324
  end
316
325
 
326
+ def set_path(path)
327
+ if path
328
+ @path = path.to_s.strip
329
+ @dirname, @basename = File.split(@path)
330
+ @value = File.join(File.basename(@dirname), @basename).strip
331
+ @path
332
+ else
333
+ @path, @dirname, @basename, @value = nil
334
+ end
335
+ end
336
+
337
+ alias_method('path=', 'set_path')
338
+
317
339
  def inspect
318
340
  {
319
341
  Upload.name =>
@@ -63,7 +63,6 @@ module Dao
63
63
  valid?
64
64
  forcing_validity?
65
65
  errors
66
- status
67
66
  ).each do |method|
68
67
  module_eval <<-__, __FILE__, __LINE__
69
68
  def #{ method }(*args, &block)
@@ -17,7 +17,9 @@ module Dao
17
17
 
18
18
  class << Validator
19
19
  def mixin(*args, &block)
20
- new(*args, &block).tap{|validator| validator.mixin = true}
20
+ new(*args, &block).tap do |validator|
21
+ validator.mixin = true
22
+ end
21
23
  end
22
24
  end
23
25
 
@@ -58,6 +60,8 @@ module Dao
58
60
  @object.validator = self
59
61
  end
60
62
 
63
+ @errors.object = @object
64
+
61
65
  #@object.extend(InstanceExec) unless @object.respond_to?(:instance_exec)
62
66
  end
63
67
 
@@ -30,10 +30,39 @@ Testing Dao::Conducer do
30
30
  assert{ c.models == [comment, post, user] }
31
31
  assert{ c.model == comment }
32
32
  assert{ c.model == c.conduces }
33
+ end
34
+
35
+ #
36
+ testing 'that the conduced model can be declared at the class level' do
37
+ user = User.new
38
+ post = Post.new
39
+ comment = Comment.new
40
+ params = {}
41
+
42
+ args = [comment, post, user, params]
43
+
44
+ c = new_conducer(*args){ conduces User }
33
45
 
34
- assert{ c.conduces(post) }
35
- assert{ c.models == [post, comment, user] }
36
- assert{ c.model == post }
46
+ assert{ c.models == [comment, post, user] }
47
+ assert{ c.model == user }
48
+ assert{ c.model == c.conduces }
49
+ end
50
+
51
+ #
52
+ testing 'that the conduced model can be declared at the instance level' do
53
+ user = User.new
54
+ post = Post.new
55
+ comment = Comment.new
56
+ params = {}
57
+
58
+ args = [comment, post, user, params]
59
+
60
+ c = new_conducer(*args)
61
+
62
+ c.conduces(user)
63
+
64
+ assert{ c.models == [user, comment, post] }
65
+ assert{ c.model == user }
37
66
  assert{ c.model == c.conduces }
38
67
  end
39
68
  end
@@ -80,10 +109,10 @@ Testing Dao::Conducer do
80
109
  assert{ c.instance_variable_get('@post') == post }
81
110
 
82
111
  expected = Map.new
83
- expected.update :user => user.attributes
84
- expected.update :post => post.attributes
85
- expected.update comment.attributes
86
- expected.update params
112
+ expected.add :user => user.attributes
113
+ expected.add :post => post.attributes
114
+ expected.add comment.attributes
115
+ expected.add params
87
116
 
88
117
  assert{ c.attributes =~ expected }
89
118
  assert{ c.instance_variable_get('@comment') == comment }
@@ -151,6 +180,15 @@ Testing Dao::Conducer do
151
180
  end
152
181
  end
153
182
 
183
+ #
184
+ testing 'that conducers *fold* in attributes' do
185
+ c = new_conducer
186
+
187
+ assert{ c.update_attributes :key => {:a => :b} }
188
+ assert{ c.update_attributes :key => {:nested => {:a => :b}} }
189
+ assert{ c.attributes =~ {:key => {:a => :b, :nested => {:a => :b}}} }
190
+ end
191
+
154
192
  ##
155
193
  #
156
194
  context :teh_default_save do
@@ -451,6 +489,8 @@ Testing Dao::Conducer do
451
489
 
452
490
  #
453
491
  testing 'that the default save uses the mounted _value and _clears it' do
492
+ begin
493
+ $pry=true
454
494
  conducer_class =
455
495
  new_conducer_class do
456
496
  mount Dao::Upload, :up, :placeholder => '/images/foo.jpg'
@@ -461,7 +501,7 @@ Testing Dao::Conducer do
461
501
  up = Upload.new(path)
462
502
  comment = Comment.new
463
503
 
464
- c = conducer_class.new( comment, :up => {:file => up} )
504
+ c = conducer_class.new( comment, :up => {:file => Upload.new(path)} )
465
505
 
466
506
  upload = assert{ c.get(:up) }
467
507
  assert{ upload.is_a?(Dao::Upload) }
@@ -476,6 +516,9 @@ Testing Dao::Conducer do
476
516
  value_was_cleared = assert{ !test(?f, upload.path) }
477
517
 
478
518
  assert{ test(?s, path) }
519
+ ensure
520
+ $pry=false
521
+ end
479
522
  end
480
523
  end
481
524
 
@@ -607,6 +650,10 @@ protected
607
650
  def initialize(path)
608
651
  super(IO.read(@path = path))
609
652
  end
653
+
654
+ def dup
655
+ self.class.new(path)
656
+ end
610
657
  end
611
658
 
612
659
  class Model
@@ -670,7 +717,7 @@ protected
670
717
  end
671
718
 
672
719
  def inspect(*args, &block)
673
- "#{ self.class.name }( #{ attributes.inspect } )"
720
+ "#{ self.class.name }(#{ attributes.inspect.strip })"
674
721
  end
675
722
 
676
723
  def errors
@@ -0,0 +1,81 @@
1
+ # -*- encoding : utf-8 -*-
2
+ Testing Dao::Errors do
3
+
4
+ testing 'that conducer-less error objects scopes keys in a generic fashion' do
5
+ e = Dao::Errors.new
6
+
7
+ e.add 'is fucked'
8
+ e.add 'foo is fucked'
9
+
10
+ actual = e.to_text
11
+
12
+ expected = <<-__
13
+ ---
14
+ global:
15
+ - is fucked
16
+ - foo is fucked
17
+ __
18
+
19
+ assert compress(actual) == compress(expected)
20
+ end
21
+
22
+ testing 'that conducer-based error objects scope keys in a model_name based fashion' do
23
+ c = new_foo_conducer
24
+
25
+ e = c.errors
26
+
27
+ e.add 'is fucked'
28
+ e.add 'foo is fucked'
29
+ e.add :first_name, 'is fucked'
30
+ e.add :last_name, 'is fucked'
31
+
32
+ actual = e.to_text
33
+
34
+ expected = <<-__
35
+ ---
36
+ foo:
37
+ - is fucked
38
+ - foo is fucked
39
+ foo.first_name:
40
+ - is fucked
41
+ foo.last_name:
42
+ - is fucked
43
+ __
44
+
45
+ assert compress(actual) == compress(expected)
46
+ end
47
+
48
+
49
+
50
+ protected
51
+ def compress(string)
52
+ string.to_s.gsub(/\s/, '')
53
+ end
54
+ def new_foo_conducer_class(&block)
55
+ const = :FooConducer
56
+ Object.send(:remove_const, const) if Object.send(:const_defined?, const)
57
+ name = const.to_s
58
+ c = assert{ Class.new(Dao::Conducer){ self.name = name } }
59
+ Object.send(:const_set, const, c)
60
+ assert{ c.name == 'FooConducer' }
61
+ assert{ c.model_name == 'Foo' }
62
+ assert{ c.table_name == 'foos' && c.collection_name == 'foos' }
63
+ assert{ c.class_eval(&block); true } if block
64
+ c
65
+ end
66
+ alias_method :new_conducer_class, :new_foo_conducer_class
67
+
68
+ def new_foo_conducer(*args, &block)
69
+ assert{ new_foo_conducer_class(&block).new(*args) }
70
+ end
71
+ alias_method :new_conducer, :new_foo_conducer
72
+ end
73
+
74
+ BEGIN {
75
+ testdir = File.dirname(File.expand_path(__FILE__))
76
+ rootdir = File.dirname(testdir)
77
+ libdir = File.join(rootdir, 'lib')
78
+ require File.join(libdir, 'dao')
79
+ require File.join(testdir, 'testing')
80
+ require 'stringio'
81
+ }