dao 7.0.0 → 8.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -86,14 +86,10 @@ module Dao
86
86
  # instance methods
87
87
  #
88
88
  %w[
89
- attributes
90
- form
91
89
  params
92
- errors
93
90
  messages
94
91
  models
95
92
  model
96
- conduces
97
93
  ].each{|attr| fattr(attr)}
98
94
 
99
95
  # ctors
@@ -323,6 +319,10 @@ module Dao
323
319
  update_attributes(attributes)
324
320
  end
325
321
 
322
+ def attributes
323
+ @attributes
324
+ end
325
+
326
326
  def set(*args, &block)
327
327
  update_attributes(*args, &block)
328
328
  end
@@ -399,10 +399,10 @@ module Dao
399
399
  end
400
400
 
401
401
  def id_for(object)
402
- model?(object) ? object.id : object
402
+ modelish?(object) ? object.id : object
403
403
  end
404
404
 
405
- def model?(object)
405
+ def modelish?(object)
406
406
  object.respond_to?(:persisted?)
407
407
  end
408
408
 
@@ -478,10 +478,6 @@ module Dao
478
478
  Dao.key_for(key)
479
479
  end
480
480
 
481
- def errors
482
- validator.errors
483
- end
484
-
485
481
  def model_name
486
482
  self.class.model_name
487
483
  end
@@ -71,7 +71,7 @@ module Dao
71
71
  when Map
72
72
  hash = Hash.new
73
73
  hashlike.depth_first_each do |key, value|
74
- index = key.pop if key.last.is_a?(Integer)
74
+ _ = key.pop if key.last.is_a?(Integer)
75
75
  (hash[key] ||= []).push(value)
76
76
  end
77
77
  hash
@@ -183,11 +183,12 @@ module Dao
183
183
  def json_for(object, options = {})
184
184
  object = object.as_json if object.respond_to?(:as_json)
185
185
 
186
- options = options.empty? ? Map.for(options) : options
187
- options[:pretty] = json_pretty? unless options.has_key?(:pretty)
186
+ pretty = (options.delete(:pretty) || json_pretty?)
187
+
188
+ generate = pretty ? :pretty_generate : :generate
188
189
 
189
190
  begin
190
- MultiJson.dump(object, options)
191
+ JSON.send(generate, object, options)
191
192
  rescue Object => _
192
193
  YAML.load( object.to_yaml ).to_json
193
194
  end
@@ -231,21 +232,9 @@ module Dao
231
232
  end
232
233
  end
233
234
 
234
-
235
- {
236
- 'ffi-uuid' => proc{|*args| FFI::UUID.generate_time.to_s},
237
- 'uuidtools' => proc{|*args| UUIDTools::UUID.timestamp_create.to_s},
238
- 'uuid' => proc{|*args| UUID.generate.to_s},
239
- }.each do |lib, implementation|
240
- begin
241
- require(lib)
242
- define_method(:uuid, &implementation)
243
- break
244
- rescue LoadError
245
- nil
246
- end
235
+ def uuid
236
+ SecureRandom.uuid
247
237
  end
248
- abort 'no suitable uuid generation library detected' unless method_defined?(:uuid)
249
238
 
250
239
  def ensure_interface!(object, *interface)
251
240
  interface.flatten.compact.each do |method|
@@ -0,0 +1,259 @@
1
+ module Dao
2
+ module Wrap
3
+ def Wrap.included(other)
4
+ super
5
+ ensure
6
+ other.send(:instance_eval, &ClassMethods)
7
+ other.send(:class_eval, &InstanceMethods)
8
+ end
9
+
10
+ def Wrap.code_for(method)
11
+ name = method.name.to_s
12
+ arity = method.arity
13
+
14
+ case
15
+ when arity == 0
16
+ signature = <<-__.strip
17
+ def #{ name }(&block)
18
+ args = []
19
+ __
20
+
21
+ when arity < 0
22
+ argv = Array.new(arity.abs - 1){|i| "arg#{ i }"}
23
+ argv.push('*args')
24
+ argv = argv.join(', ')
25
+
26
+ signature = <<-__.strip
27
+ def #{ name }(#{ argv }, &block)
28
+ args = [#{ argv }]
29
+ __
30
+
31
+ when arity > 0
32
+ argv = Array.new(arity){|i| "arg#{ i }"}
33
+ argv = argv.join(', ')
34
+
35
+ signature = <<-__.strip
36
+ def #{ name }(#{ argv }, &block)
37
+ args = [#{ argv }]
38
+ __
39
+ end
40
+
41
+ code =
42
+ <<-__
43
+ #{ signature.strip }
44
+
45
+ if running_callbacks?(#{ name.inspect })
46
+ return wrapped_#{ name }(*args, &block)
47
+ end
48
+
49
+ running_callbacks(#{ name.inspect }) do
50
+ catch(:halt) do
51
+ return false if run_callbacks(:before, #{ name.inspect }, args)==false
52
+
53
+ begin
54
+ result = wrapped_#{ name }(*args, &block)
55
+ ensure
56
+ run_callbacks(:after, #{ name.inspect }, [result]) unless $!
57
+ end
58
+ end
59
+ end
60
+ end
61
+ __
62
+
63
+ return code
64
+ end
65
+
66
+ ClassMethods = proc do
67
+ def method_added(name)
68
+ return super if wrapping?
69
+ begin
70
+ super
71
+ ensure
72
+ wrap!(name) if wrapped?(name)
73
+ end
74
+ end
75
+
76
+ def include(other)
77
+ super
78
+ ensure
79
+ other.instance_methods.each do |name|
80
+ if wrapped?(name)
81
+ begin
82
+ remove_method(name)
83
+ rescue NameError
84
+ nil
85
+ end
86
+ wrap!(name)
87
+ end
88
+ end
89
+ end
90
+
91
+ def wrap(name, *args, &block)
92
+ wrapped!(name)
93
+
94
+ wrap!(name) if
95
+ begin
96
+ instance_method(name)
97
+ true
98
+ rescue NameError
99
+ false
100
+ end
101
+ end
102
+
103
+ def wrapped!(name)
104
+ name = name.to_s
105
+ wrapped.push(name) unless wrapped.include?(name)
106
+ name
107
+ end
108
+
109
+ def wrapped
110
+ @wrapped ||= []
111
+ end
112
+
113
+ def wrapped?(name)
114
+ ancestors.any?{|ancestor| ancestor.respond_to?(:wrapped) and ancestor.wrapped.include?(name.to_s)}
115
+ end
116
+
117
+ def wrap!(name)
118
+ name = name.to_s
119
+ method = instance_method(name)
120
+
121
+ wrapping! name do
122
+ name = name.to_s
123
+ wrapped_name = "wrapped_#{ name }"
124
+
125
+ begin
126
+ remove_method(wrapped_name)
127
+ rescue NameError
128
+ nil
129
+ end
130
+
131
+ alias_method(wrapped_name, name)
132
+
133
+ module_eval(Wrap.code_for(method))
134
+ end
135
+ end
136
+
137
+ def wrapping!(name, &block)
138
+ name = name.to_s
139
+ @wrapping ||= []
140
+
141
+ return if @wrapping.last == name
142
+
143
+ @wrapping.push(name)
144
+
145
+ begin
146
+ block.call
147
+ ensure
148
+ @wrapping.pop
149
+ end
150
+ end
151
+
152
+ def wrapping?(*name)
153
+ @wrapping ||= []
154
+
155
+ if name.empty?
156
+ !@wrapping.empty?
157
+ else
158
+ @wrapping.last == name.last.to_s
159
+ end
160
+ end
161
+
162
+ def callbacks
163
+ @callbacks ||= Map.new
164
+ end
165
+
166
+ def initialize_callbacks!(name)
167
+ callbacks[name] ||= Map[ :before, [], :after, [] ]
168
+ callbacks[name]
169
+ end
170
+
171
+ def before(name, *args, &block)
172
+ wrap(name) unless wrapped?(name)
173
+ name = wrap_expand_aliases(name)
174
+ cb = initialize_callbacks!(name)
175
+ cb.before.push(args.shift || block)
176
+ end
177
+
178
+ def after(name, *args, &block)
179
+ wrap(name) unless wrapped?(name)
180
+ name = wrap_expand_aliases(name)
181
+ cb = initialize_callbacks!(name)
182
+ cb.after.push(args.shift || block)
183
+ end
184
+
185
+ def wrap_aliases
186
+ @@wrap_aliases ||= Hash.new
187
+ end
188
+
189
+ def wrap_alias(dst, src)
190
+ wrap_aliases[dst.to_s] = src.to_s
191
+ end
192
+
193
+ def wrap_expand_aliases(name)
194
+ name = name.to_s
195
+ loop do
196
+ break unless wrap_aliases.has_key?(name)
197
+ name = wrap_aliases[name]
198
+ end
199
+ name
200
+ end
201
+ end
202
+
203
+ InstanceMethods = proc do
204
+ def running_callbacks(name, &block)
205
+ name = name.to_s
206
+ @running_callbacks ||= []
207
+ return block.call() if @running_callbacks.last == name
208
+
209
+ @running_callbacks.push(name)
210
+
211
+ begin
212
+ block.call()
213
+ ensure
214
+ @running_callbacks.pop
215
+ end
216
+ end
217
+
218
+ def running_callbacks?(*name)
219
+ @running_callbacks ||= []
220
+
221
+ if name.empty?
222
+ @running_callbacks.last
223
+ else
224
+ @running_callbacks.last == name.last.to_s
225
+ end
226
+ end
227
+
228
+ def run_callbacks(which, name, argv)
229
+ which = which.to_s.to_sym
230
+ name = name.to_s
231
+ list = []
232
+
233
+ self.class.ancestors.each do |ancestor|
234
+ next unless ancestor.respond_to?(:callbacks)
235
+
236
+ if ancestor.callbacks.is_a?(Map) and ancestor.callbacks[name].is_a?(Map)
237
+ callbacks = ancestor.callbacks[name][which]
238
+ accumulate = (which == :before ? :unshift : :push)
239
+ list.send(accumulate, *callbacks) if callbacks.is_a?(Array)
240
+ end
241
+ end
242
+
243
+ list.each do |callback|
244
+ block = callback.respond_to?(:call) ? callback : proc{ send(callback.to_s.to_sym) }
245
+ args = argv.slice(0 .. (block.arity > 0 ? block.arity : -1))
246
+ result = instance_exec(*args, &block)
247
+ return false if result == false
248
+ end
249
+
250
+ true
251
+ end
252
+
253
+ def halt!(*args)
254
+ value = args.size == 0 ? false : args.shift
255
+ throw(:halt, value)
256
+ end
257
+ end
258
+ end
259
+ end
@@ -498,7 +498,7 @@ $pry=true
498
498
 
499
499
  path = File.join(File.dirname(__FILE__), 'data/han-solo.jpg')
500
500
  assert{ test(?s, path) }
501
- up = Upload.new(path)
501
+ _up = Upload.new(path)
502
502
  comment = Comment.new
503
503
 
504
504
  c = conducer_class.new( comment, :up => {:file => Upload.new(path)} )
@@ -512,8 +512,8 @@ $pry=true
512
512
 
513
513
  assert{ c.save }
514
514
 
515
- value_was_relayed = assert{ comment.attributes[:up] == upload._value }
516
- value_was_cleared = assert{ !test(?f, upload.path) }
515
+ _value_was_relayed = assert{ comment.attributes[:up] == upload._value }
516
+ _value_was_cleared = assert{ !test(?f, upload.path) }
517
517
 
518
518
  assert{ test(?s, path) }
519
519
  ensure
@@ -705,7 +705,7 @@ protected
705
705
 
706
706
  def method_missing(method, *args, &block)
707
707
  re = /^([^=!?]+)([=!?])?$/imox
708
- matched, key, suffix = re.match(method.to_s).to_a
708
+ _matched, key, suffix = re.match(method.to_s).to_a
709
709
 
710
710
  case suffix
711
711
  when '=' then attributes.set(key, args.first)
@@ -2,8 +2,8 @@
2
2
  require_relative 'test_helper'
3
3
  class DaoFormTest < ::Dao::TestCase
4
4
  test '.new' do
5
- form = new_form()
6
- form = new_named_form()
5
+ _ = new_form()
6
+ _ = new_named_form()
7
7
  end
8
8
 
9
9
  test 'name_for' do
@@ -111,8 +111,9 @@ class DaoValidationsTest < ::Dao::TestCase
111
111
  end
112
112
 
113
113
  test 'simple validates_confirmation_of' do
114
+ =begin
114
115
  return :pending
115
-
116
+ =end
116
117
  api_class =
117
118
  Dao.api do
118
119
  endpoint('/foobar'){
@@ -136,7 +137,6 @@ class DaoValidationsTest < ::Dao::TestCase
136
137
  #
137
138
  test 'that validations clear only that which they know about' do
138
139
  params = Dao::Params.new
139
- errors = params.errors
140
140
 
141
141
  assert{ params.validates(:email){|email| email.to_s.split(/@/).size == 2} }
142
142
  assert{ params.validates(:password){|password| password == 'pa$$w0rd'} }
@@ -0,0 +1,57 @@
1
+ NAME
2
+ wrap
3
+
4
+ SYNOPSIS
5
+ non-sucking :before and :after filters for any ruby class
6
+
7
+ DESCRIPTION
8
+ yes yes, active_support does this. but crapily. with active_support you'll
9
+ need to do this
10
+
11
+
12
+ class Record
13
+ include ActiveSupport::Callbacks
14
+ define_callbacks :save
15
+
16
+ def save
17
+ run_callbacks :save do
18
+ puts "- save"
19
+ end
20
+ end
21
+ end
22
+
23
+ but hey, if a subclass forgets to call 'super' or doesn't manually run
24
+ 'run_callbacks' the codez are *screwed*. that sux. why not this?
25
+
26
+
27
+ class Record
28
+ include Wrap
29
+
30
+ wrap :save
31
+ end
32
+
33
+
34
+ yes, it's that simple. you can now do
35
+
36
+ class SubRecord < Record
37
+ before :save do
38
+ special_sauce
39
+ end
40
+
41
+ def save
42
+ no_special_sauce
43
+ end
44
+ end
45
+
46
+ did you get that? the :before and :after hooks will be called no matter
47
+ what the subclass does. the method will be wrapped, period. no special
48
+ work required. of course, if the sublcass messes with 'method_added' their
49
+ will be hell to pay. that's the price for simplicity.
50
+
51
+ the callbacks are very close, but not identical to active_supports. you can
52
+ return 'false' to halt the chain, but you can also simply call 'halt!'.
53
+ another neat trick is that :before callbacks will be called with the
54
+ arguments to the wrapped method itself iff possible and :after callbacks
55
+ will be called with the result of the wrapped method, iff possible.
56
+
57
+ the test suite reads pretty damn clean. have a go.