ant-mapper 0.0.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.
- data/CHANGE +6 -0
- data/MIT-LICENSE +20 -0
- data/README +25 -0
- data/ant.gemspec +48 -0
- data/data.tch +0 -0
- data/examples/account.rb +71 -0
- data/examples/data.tch +0 -0
- data/examples/light_cloud.yml +18 -0
- data/examples/user.rb +84 -0
- data/init.rb +4 -0
- data/lib/ant.rb +7 -0
- data/lib/ant_mapper.rb +10 -0
- data/lib/ant_mapper/adapters/light_cloud.rb +59 -0
- data/lib/ant_mapper/adapters/tokyo_cabinet.rb +42 -0
- data/lib/ant_mapper/adapters/tokyo_tyrant.rb +14 -0
- data/lib/ant_mapper/base.rb +367 -0
- data/lib/ant_mapper/callbacks.rb +180 -0
- data/lib/ant_mapper/observer.rb +180 -0
- data/lib/ant_mapper/validations.rb +687 -0
- data/lib/ant_support.rb +4 -0
- data/lib/ant_support/callbacks.rb +303 -0
- data/lib/ant_support/core_ext.rb +4 -0
- data/lib/ant_support/core_ext/array.rb +5 -0
- data/lib/ant_support/core_ext/array/extract_options.rb +20 -0
- data/lib/ant_support/core_ext/blank.rb +58 -0
- data/lib/ant_support/core_ext/class.rb +3 -0
- data/lib/ant_support/core_ext/class/attribute_accessors.rb +54 -0
- data/lib/ant_support/core_ext/class/inheritable_attributes.rb +140 -0
- data/lib/ant_support/core_ext/class/removal.rb +50 -0
- data/lib/ant_support/core_ext/duplicable.rb +43 -0
- data/lib/ant_support/core_ext/enumerable.rb +72 -0
- data/lib/ant_support/core_ext/hash.rb +6 -0
- data/lib/ant_support/core_ext/hash/keys.rb +52 -0
- data/lib/ant_support/core_ext/module.rb +16 -0
- data/lib/ant_support/core_ext/module/aliasing.rb +74 -0
- data/lib/ant_support/core_ext/module/attr_accessor_with_default.rb +31 -0
- data/lib/ant_support/core_ext/module/attribute_accessors.rb +58 -0
- data/lib/ant_support/core_ext/object.rb +1 -0
- data/lib/ant_support/core_ext/object/extending.rb +80 -0
- data/lib/ant_support/core_ext/string.rb +7 -0
- data/lib/ant_support/core_ext/string/inflections.rb +51 -0
- data/spec/case/callbacks_observers_test.rb +38 -0
- data/spec/case/callbacks_test.rb +417 -0
- data/spec/case/create_object_test.rb +56 -0
- data/spec/case/set_class_name_test.rb +17 -0
- data/spec/case/validations_test.rb +1482 -0
- data/spec/helper.rb +15 -0
- data/spec/light_cloud.yml +18 -0
- data/spec/model/account.rb +3 -0
- data/spec/model/topic.rb +28 -0
- data/spec/model/user.rb +4 -0
- metadata +125 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
class Module
|
2
|
+
# Declare an attribute accessor with an initial default return value.
|
3
|
+
#
|
4
|
+
# To give attribute <tt>:age</tt> the initial value <tt>25</tt>:
|
5
|
+
#
|
6
|
+
# class Person
|
7
|
+
# attr_accessor_with_default :age, 25
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# some_person.age
|
11
|
+
# => 25
|
12
|
+
# some_person.age = 26
|
13
|
+
# some_person.age
|
14
|
+
# => 26
|
15
|
+
#
|
16
|
+
# To give attribute <tt>:element_name</tt> a dynamic default value, evaluated
|
17
|
+
# in scope of self:
|
18
|
+
#
|
19
|
+
# attr_accessor_with_default(:element_name) { name.underscore }
|
20
|
+
#
|
21
|
+
def attr_accessor_with_default(sym, default = nil, &block)
|
22
|
+
raise 'Default value or block required' unless !default.nil? || block
|
23
|
+
define_method(sym, block_given? ? block : Proc.new { default })
|
24
|
+
module_eval(<<-EVAL, __FILE__, __LINE__)
|
25
|
+
def #{sym}=(value)
|
26
|
+
class << self; attr_reader :#{sym} end
|
27
|
+
@#{sym} = value
|
28
|
+
end
|
29
|
+
EVAL
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Extends the module object with module and instance accessors for class attributes,
|
2
|
+
# just like the native attr* accessors for instance attributes.
|
3
|
+
#
|
4
|
+
# module AppConfiguration
|
5
|
+
# mattr_accessor :google_api_key
|
6
|
+
# self.google_api_key = "123456789"
|
7
|
+
#
|
8
|
+
# mattr_accessor :paypal_url
|
9
|
+
# self.paypal_url = "www.sandbox.paypal.com"
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# AppConfiguration.google_api_key = "overriding the api key!"
|
13
|
+
class Module
|
14
|
+
def mattr_reader(*syms)
|
15
|
+
syms.each do |sym|
|
16
|
+
next if sym.is_a?(Hash)
|
17
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
18
|
+
unless defined? @@#{sym}
|
19
|
+
@@#{sym} = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.#{sym}
|
23
|
+
@@#{sym}
|
24
|
+
end
|
25
|
+
|
26
|
+
def #{sym}
|
27
|
+
@@#{sym}
|
28
|
+
end
|
29
|
+
EOS
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def mattr_writer(*syms)
|
34
|
+
options = syms.extract_options!
|
35
|
+
syms.each do |sym|
|
36
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
37
|
+
unless defined? @@#{sym}
|
38
|
+
@@#{sym} = nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.#{sym}=(obj)
|
42
|
+
@@#{sym} = obj
|
43
|
+
end
|
44
|
+
|
45
|
+
#{"
|
46
|
+
def #{sym}=(obj)
|
47
|
+
@@#{sym} = obj
|
48
|
+
end
|
49
|
+
" unless options[:instance_writer] == false }
|
50
|
+
EOS
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def mattr_accessor(*syms)
|
55
|
+
mattr_reader(*syms)
|
56
|
+
mattr_writer(*syms)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'ant_support/core_ext/object/extending'
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class Object
|
2
|
+
def remove_subclasses_of(*superclasses) #:nodoc:
|
3
|
+
Class.remove_class(*subclasses_of(*superclasses))
|
4
|
+
end
|
5
|
+
|
6
|
+
begin
|
7
|
+
ObjectSpace.each_object(Class.new) {}
|
8
|
+
|
9
|
+
# Exclude this class unless it's a subclass of our supers and is defined.
|
10
|
+
# We check defined? in case we find a removed class that has yet to be
|
11
|
+
# garbage collected. This also fails for anonymous classes -- please
|
12
|
+
# submit a patch if you have a workaround.
|
13
|
+
def subclasses_of(*superclasses) #:nodoc:
|
14
|
+
subclasses = []
|
15
|
+
|
16
|
+
superclasses.each do |sup|
|
17
|
+
ObjectSpace.each_object(class << sup; self; end) do |k|
|
18
|
+
if k != sup && (k.name.blank? || eval("defined?(::#{k}) && ::#{k}.object_id == k.object_id"))
|
19
|
+
subclasses << k
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
subclasses
|
25
|
+
end
|
26
|
+
rescue RuntimeError
|
27
|
+
# JRuby and any implementations which cannot handle the objectspace traversal
|
28
|
+
# above fall back to this implementation
|
29
|
+
def subclasses_of(*superclasses) #:nodoc:
|
30
|
+
subclasses = []
|
31
|
+
|
32
|
+
superclasses.each do |sup|
|
33
|
+
ObjectSpace.each_object(Class) do |k|
|
34
|
+
if superclasses.any? { |superclass| k < superclass } &&
|
35
|
+
(k.name.blank? || eval("defined?(::#{k}) && ::#{k}.object_id == k.object_id"))
|
36
|
+
subclasses << k
|
37
|
+
end
|
38
|
+
end
|
39
|
+
subclasses.uniq!
|
40
|
+
end
|
41
|
+
subclasses
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def extended_by #:nodoc:
|
46
|
+
ancestors = class << self; ancestors end
|
47
|
+
ancestors.select { |mod| mod.class == Module } - [ Object, Kernel ]
|
48
|
+
end
|
49
|
+
|
50
|
+
def extend_with_included_modules_from(object) #:nodoc:
|
51
|
+
object.extended_by.each { |mod| extend mod }
|
52
|
+
end
|
53
|
+
|
54
|
+
unless defined? instance_exec # 1.9
|
55
|
+
module InstanceExecMethods #:nodoc:
|
56
|
+
end
|
57
|
+
include InstanceExecMethods
|
58
|
+
|
59
|
+
# Evaluate the block with the given arguments within the context of
|
60
|
+
# this object, so self is set to the method receiver.
|
61
|
+
#
|
62
|
+
# From Mauricio's http://eigenclass.org/hiki/bounded+space+instance_exec
|
63
|
+
def instance_exec(*args, &block)
|
64
|
+
begin
|
65
|
+
old_critical, Thread.critical = Thread.critical, true
|
66
|
+
n = 0
|
67
|
+
n += 1 while respond_to?(method_name = "__instance_exec#{n}")
|
68
|
+
InstanceExecMethods.module_eval { define_method(method_name, &block) }
|
69
|
+
ensure
|
70
|
+
Thread.critical = old_critical
|
71
|
+
end
|
72
|
+
|
73
|
+
begin
|
74
|
+
send(method_name, *args)
|
75
|
+
ensure
|
76
|
+
InstanceExecMethods.module_eval { remove_method(method_name) } rescue nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module AntSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module String #:nodoc:
|
4
|
+
module Inflections
|
5
|
+
|
6
|
+
# Ruby 1.9 introduces an inherit argument for Module#const_get and
|
7
|
+
# #const_defined? and changes their default behavior.
|
8
|
+
if Module.method(:const_get).arity == 1
|
9
|
+
# Tries to find a constant with the name specified in the argument string:
|
10
|
+
#
|
11
|
+
# "Module".constantize # => Module
|
12
|
+
# "Test::Unit".constantize # => Test::Unit
|
13
|
+
#
|
14
|
+
# The name is assumed to be the one of a top-level constant, no matter whether
|
15
|
+
# it starts with "::" or not. No lexical context is taken into account:
|
16
|
+
#
|
17
|
+
# C = 'outside'
|
18
|
+
# module M
|
19
|
+
# C = 'inside'
|
20
|
+
# C # => 'inside'
|
21
|
+
# "C".constantize # => 'outside', same as ::C
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# NameError is raised when the name is not in CamelCase or the constant is
|
25
|
+
# unknown.
|
26
|
+
def constantize
|
27
|
+
names = self.split('::')
|
28
|
+
names.shift if names.empty? || names.first.empty?
|
29
|
+
|
30
|
+
constant = Object
|
31
|
+
names.each do |name|
|
32
|
+
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
33
|
+
end
|
34
|
+
constant
|
35
|
+
end
|
36
|
+
else
|
37
|
+
def constantize #:nodoc:
|
38
|
+
names = self.split('::')
|
39
|
+
names.shift if names.empty? || names.first.empty?
|
40
|
+
|
41
|
+
constant = Object
|
42
|
+
names.each do |name|
|
43
|
+
constant = constant.const_get(name, false) || constant.const_missing(name)
|
44
|
+
end
|
45
|
+
constant
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "../helper"
|
2
|
+
|
3
|
+
class Comment < AntMapper::Base
|
4
|
+
attr_accessor :callers
|
5
|
+
|
6
|
+
before_validation :record_callers
|
7
|
+
|
8
|
+
def after_validation
|
9
|
+
record_callers
|
10
|
+
end
|
11
|
+
|
12
|
+
def record_callers
|
13
|
+
callers << self.class if callers
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class CommentObserver < AntMapper::Observer
|
18
|
+
attr_accessor :callers
|
19
|
+
|
20
|
+
def after_validation(model)
|
21
|
+
callers << self.class if callers
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class CallbacksObserversTest < Test::Unit::TestCase
|
26
|
+
def test_model_callbacks_fire_before_observers_are_notified
|
27
|
+
callers = []
|
28
|
+
|
29
|
+
comment = Comment.new
|
30
|
+
comment.callers = callers
|
31
|
+
|
32
|
+
CommentObserver.instance.callers = callers
|
33
|
+
|
34
|
+
comment.valid?
|
35
|
+
|
36
|
+
assert_equal [Comment, Comment, CommentObserver], callers, "model callbacks did not fire before observers were notified"
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,417 @@
|
|
1
|
+
require "../helper"
|
2
|
+
|
3
|
+
class User < AntMapper::Base
|
4
|
+
set_primary_key :email
|
5
|
+
set_attributes :name,:email,:password,:salary
|
6
|
+
end
|
7
|
+
|
8
|
+
class CallbackDeveloper < AntMapper::Base
|
9
|
+
self.class_name = 'User'
|
10
|
+
|
11
|
+
set_primary_key :email
|
12
|
+
set_attributes :name,:email,:password,:salary
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def callback_string(callback_method)
|
16
|
+
"history << [#{callback_method.to_sym.inspect}, :string]"
|
17
|
+
end
|
18
|
+
|
19
|
+
def callback_proc(callback_method)
|
20
|
+
Proc.new { |model| model.history << [callback_method, :proc] }
|
21
|
+
end
|
22
|
+
|
23
|
+
def define_callback_method(callback_method)
|
24
|
+
define_method("#{callback_method}_method") do |model|
|
25
|
+
model.history << [callback_method, :method]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def callback_object(callback_method)
|
30
|
+
klass = Class.new
|
31
|
+
klass.send(:define_method, callback_method) do |model|
|
32
|
+
model.history << [callback_method, :object]
|
33
|
+
end
|
34
|
+
klass.new
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
AntMapper::Callbacks::CALLBACKS.each do |callback_method|
|
39
|
+
callback_method_sym = callback_method.to_sym
|
40
|
+
define_callback_method(callback_method_sym)
|
41
|
+
send(callback_method, callback_method_sym)
|
42
|
+
send(callback_method, callback_string(callback_method_sym))
|
43
|
+
send(callback_method, callback_proc(callback_method_sym))
|
44
|
+
send(callback_method, callback_object(callback_method_sym))
|
45
|
+
send(callback_method) { |model| model.history << [callback_method_sym, :block] }
|
46
|
+
end
|
47
|
+
|
48
|
+
def history
|
49
|
+
@history ||= []
|
50
|
+
end
|
51
|
+
|
52
|
+
# after_initialize and after_find are invoked only if instance methods have been defined.
|
53
|
+
def after_initialize
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def after_find
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class ParentDeveloper < AntMapper::Base
|
62
|
+
self.class_name = 'User'
|
63
|
+
set_primary_key :email
|
64
|
+
set_attributes :name,:email,:password,:salary
|
65
|
+
|
66
|
+
attr_accessor :after_save_called
|
67
|
+
before_validation {|record| record.after_save_called = true}
|
68
|
+
end
|
69
|
+
|
70
|
+
class ChildDeveloper < ParentDeveloper
|
71
|
+
self.class_name = 'User'
|
72
|
+
set_primary_key :email
|
73
|
+
set_attributes :name,:email,:password,:salary
|
74
|
+
end
|
75
|
+
|
76
|
+
class RecursiveCallbackDeveloper < AntMapper::Base
|
77
|
+
self.class_name = 'User'
|
78
|
+
set_primary_key :email
|
79
|
+
set_attributes :name,:email,:password,:salary
|
80
|
+
|
81
|
+
before_save :on_before_save
|
82
|
+
after_save :on_after_save
|
83
|
+
|
84
|
+
attr_reader :on_before_save_called, :on_after_save_called
|
85
|
+
|
86
|
+
def on_before_save
|
87
|
+
@on_before_save_called ||= 0
|
88
|
+
@on_before_save_called += 1
|
89
|
+
save unless @on_before_save_called > 1
|
90
|
+
end
|
91
|
+
|
92
|
+
def on_after_save
|
93
|
+
@on_after_save_called ||= 0
|
94
|
+
@on_after_save_called += 1
|
95
|
+
save unless @on_after_save_called > 1
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class ImmutableDeveloper < AntMapper::Base
|
100
|
+
self.class_name = 'User'
|
101
|
+
set_primary_key :email
|
102
|
+
set_attributes :name,:email,:password,:salary
|
103
|
+
|
104
|
+
validates_inclusion_of :salary, :in => 50000..200000
|
105
|
+
|
106
|
+
before_save :cancel
|
107
|
+
before_destroy :cancel
|
108
|
+
|
109
|
+
def cancelled?
|
110
|
+
@cancelled == true
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
def cancel
|
115
|
+
@cancelled = true
|
116
|
+
false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class ImmutableMethodDeveloper < AntMapper::Base
|
121
|
+
self.class_name = 'User'
|
122
|
+
set_primary_key :email
|
123
|
+
set_attributes :name,:email,:password,:salary
|
124
|
+
|
125
|
+
validates_inclusion_of :salary, :in => 50000..200000
|
126
|
+
|
127
|
+
def cancelled?
|
128
|
+
@cancelled == true
|
129
|
+
end
|
130
|
+
|
131
|
+
def before_save
|
132
|
+
@cancelled = true
|
133
|
+
false
|
134
|
+
end
|
135
|
+
|
136
|
+
def before_destroy
|
137
|
+
@cancelled = true
|
138
|
+
false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class CallbackCancellationDeveloper < AntMapper::Base
|
143
|
+
self.class_name = 'User'
|
144
|
+
set_primary_key :email
|
145
|
+
set_attributes :name,:email,:password,:salary
|
146
|
+
|
147
|
+
def before_create
|
148
|
+
false
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class CallbacksTest < Test::Unit::TestCase
|
153
|
+
def setup
|
154
|
+
@attributes={:name=>'aaron',:email=>'aaron@nonobo.com',:password=>'123456',:salary=>100000}
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_initialize
|
158
|
+
david = CallbackDeveloper.new
|
159
|
+
assert_equal [
|
160
|
+
[ :after_initialize, :string ],
|
161
|
+
[ :after_initialize, :proc ],
|
162
|
+
[ :after_initialize, :object ],
|
163
|
+
[ :after_initialize, :block ],
|
164
|
+
], david.history
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_find
|
168
|
+
User.create(@attributes)
|
169
|
+
david = CallbackDeveloper.find(@attributes[:email])
|
170
|
+
assert_equal [
|
171
|
+
[ :after_initialize, :string ],
|
172
|
+
[ :after_initialize, :proc ],
|
173
|
+
[ :after_initialize, :object ],
|
174
|
+
[ :after_initialize, :block ],
|
175
|
+
], david.history
|
176
|
+
david.destroy
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_new_valid?
|
180
|
+
david = CallbackDeveloper.new
|
181
|
+
david.valid?
|
182
|
+
assert_equal [
|
183
|
+
[ :after_initialize, :string ],
|
184
|
+
[ :after_initialize, :proc ],
|
185
|
+
[ :after_initialize, :object ],
|
186
|
+
[ :after_initialize, :block ],
|
187
|
+
[ :before_validation, :string ],
|
188
|
+
[ :before_validation, :proc ],
|
189
|
+
[ :before_validation, :object ],
|
190
|
+
[ :before_validation, :block ],
|
191
|
+
[ :before_validation_on_create, :string ],
|
192
|
+
[ :before_validation_on_create, :proc ],
|
193
|
+
[ :before_validation_on_create, :object ],
|
194
|
+
[ :before_validation_on_create, :block ],
|
195
|
+
[ :after_validation, :string ],
|
196
|
+
[ :after_validation, :proc ],
|
197
|
+
[ :after_validation, :object ],
|
198
|
+
[ :after_validation, :block ],
|
199
|
+
[ :after_validation_on_create, :string ],
|
200
|
+
[ :after_validation_on_create, :proc ],
|
201
|
+
[ :after_validation_on_create, :object ],
|
202
|
+
[ :after_validation_on_create, :block ]
|
203
|
+
], david.history
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_existing_valid?
|
207
|
+
User.create(@attributes)
|
208
|
+
david = CallbackDeveloper.find(@attributes[:email])
|
209
|
+
david.valid?
|
210
|
+
assert_equal [
|
211
|
+
[ :after_initialize, :string ],
|
212
|
+
[ :after_initialize, :proc ],
|
213
|
+
[ :after_initialize, :object ],
|
214
|
+
[ :after_initialize, :block ],
|
215
|
+
[ :before_validation, :string ],
|
216
|
+
[ :before_validation, :proc ],
|
217
|
+
[ :before_validation, :object ],
|
218
|
+
[ :before_validation, :block ],
|
219
|
+
[ :before_validation_on_update, :string ],
|
220
|
+
[ :before_validation_on_update, :proc ],
|
221
|
+
[ :before_validation_on_update, :object ],
|
222
|
+
[ :before_validation_on_update, :block ],
|
223
|
+
[ :after_validation, :string ],
|
224
|
+
[ :after_validation, :proc ],
|
225
|
+
[ :after_validation, :object ],
|
226
|
+
[ :after_validation, :block ],
|
227
|
+
[ :after_validation_on_update, :string ],
|
228
|
+
[ :after_validation_on_update, :proc ],
|
229
|
+
[ :after_validation_on_update, :object ],
|
230
|
+
[ :after_validation_on_update, :block ]
|
231
|
+
], david.history
|
232
|
+
david.destroy
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_create
|
236
|
+
david = CallbackDeveloper.create(@attributes)
|
237
|
+
assert_equal [
|
238
|
+
[ :after_initialize, :string ],
|
239
|
+
[ :after_initialize, :proc ],
|
240
|
+
[ :after_initialize, :object ],
|
241
|
+
[ :after_initialize, :block ],
|
242
|
+
[ :before_validation, :string ],
|
243
|
+
[ :before_validation, :proc ],
|
244
|
+
[ :before_validation, :object ],
|
245
|
+
[ :before_validation, :block ],
|
246
|
+
[ :before_validation_on_create, :string ],
|
247
|
+
[ :before_validation_on_create, :proc ],
|
248
|
+
[ :before_validation_on_create, :object ],
|
249
|
+
[ :before_validation_on_create, :block ],
|
250
|
+
[ :after_validation, :string ],
|
251
|
+
[ :after_validation, :proc ],
|
252
|
+
[ :after_validation, :object ],
|
253
|
+
[ :after_validation, :block ],
|
254
|
+
[ :after_validation_on_create, :string ],
|
255
|
+
[ :after_validation_on_create, :proc ],
|
256
|
+
[ :after_validation_on_create, :object ],
|
257
|
+
[ :after_validation_on_create, :block ],
|
258
|
+
[ :before_save, :string ],
|
259
|
+
[ :before_save, :proc ],
|
260
|
+
[ :before_save, :object ],
|
261
|
+
[ :before_save, :block ],
|
262
|
+
[ :before_create, :string ],
|
263
|
+
[ :before_create, :proc ],
|
264
|
+
[ :before_create, :object ],
|
265
|
+
[ :before_create, :block ],
|
266
|
+
[ :after_create, :string ],
|
267
|
+
[ :after_create, :proc ],
|
268
|
+
[ :after_create, :object ],
|
269
|
+
[ :after_create, :block ],
|
270
|
+
[ :after_save, :string ],
|
271
|
+
[ :after_save, :proc ],
|
272
|
+
[ :after_save, :object ],
|
273
|
+
[ :after_save, :block ]
|
274
|
+
], david.history
|
275
|
+
david.destroy
|
276
|
+
end
|
277
|
+
|
278
|
+
def test_save
|
279
|
+
User.create(@attributes)
|
280
|
+
david = CallbackDeveloper.find(@attributes[:email])
|
281
|
+
david.save
|
282
|
+
assert_equal [
|
283
|
+
[ :after_initialize, :string ],
|
284
|
+
[ :after_initialize, :proc ],
|
285
|
+
[ :after_initialize, :object ],
|
286
|
+
[ :after_initialize, :block ],
|
287
|
+
[ :before_validation, :string ],
|
288
|
+
[ :before_validation, :proc ],
|
289
|
+
[ :before_validation, :object ],
|
290
|
+
[ :before_validation, :block ],
|
291
|
+
[ :before_validation_on_update, :string ],
|
292
|
+
[ :before_validation_on_update, :proc ],
|
293
|
+
[ :before_validation_on_update, :object ],
|
294
|
+
[ :before_validation_on_update, :block ],
|
295
|
+
[ :after_validation, :string ],
|
296
|
+
[ :after_validation, :proc ],
|
297
|
+
[ :after_validation, :object ],
|
298
|
+
[ :after_validation, :block ],
|
299
|
+
[ :after_validation_on_update, :string ],
|
300
|
+
[ :after_validation_on_update, :proc ],
|
301
|
+
[ :after_validation_on_update, :object ],
|
302
|
+
[ :after_validation_on_update, :block ],
|
303
|
+
[ :before_save, :string ],
|
304
|
+
[ :before_save, :proc ],
|
305
|
+
[ :before_save, :object ],
|
306
|
+
[ :before_save, :block ],
|
307
|
+
[ :before_update, :string ],
|
308
|
+
[ :before_update, :proc ],
|
309
|
+
[ :before_update, :object ],
|
310
|
+
[ :before_update, :block ],
|
311
|
+
[ :after_update, :string ],
|
312
|
+
[ :after_update, :proc ],
|
313
|
+
[ :after_update, :object ],
|
314
|
+
[ :after_update, :block ],
|
315
|
+
[ :after_save, :string ],
|
316
|
+
[ :after_save, :proc ],
|
317
|
+
[ :after_save, :object ],
|
318
|
+
[ :after_save, :block ]
|
319
|
+
], david.history
|
320
|
+
david.destroy
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_destroy
|
324
|
+
User.create(@attributes)
|
325
|
+
david = CallbackDeveloper.find(@attributes[:email])
|
326
|
+
david.destroy
|
327
|
+
assert_equal [
|
328
|
+
[ :after_initialize, :string ],
|
329
|
+
[ :after_initialize, :proc ],
|
330
|
+
[ :after_initialize, :object ],
|
331
|
+
[ :after_initialize, :block ],
|
332
|
+
[ :before_destroy, :string ],
|
333
|
+
[ :before_destroy, :proc ],
|
334
|
+
[ :before_destroy, :object ],
|
335
|
+
[ :before_destroy, :block ],
|
336
|
+
[ :after_destroy, :string ],
|
337
|
+
[ :after_destroy, :proc ],
|
338
|
+
[ :after_destroy, :object ],
|
339
|
+
[ :after_destroy, :block ]
|
340
|
+
], david.history
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_delete
|
344
|
+
User.create(@attributes)
|
345
|
+
david = CallbackDeveloper.find(@attributes[:email])
|
346
|
+
CallbackDeveloper.delete(david.object_key)
|
347
|
+
assert_equal [
|
348
|
+
[ :after_initialize, :string ],
|
349
|
+
[ :after_initialize, :proc ],
|
350
|
+
[ :after_initialize, :object ],
|
351
|
+
[ :after_initialize, :block ],
|
352
|
+
], david.history
|
353
|
+
end
|
354
|
+
|
355
|
+
def test_before_save_returning_false
|
356
|
+
User.create(@attributes)
|
357
|
+
david = ImmutableDeveloper.find(@attributes[:email])
|
358
|
+
|
359
|
+
assert david.valid?
|
360
|
+
assert !david.save
|
361
|
+
assert_raises(AntMapper::ObjectNotSaved) { david.save! }
|
362
|
+
david = ImmutableDeveloper.find(@attributes[:email])
|
363
|
+
david.salary = 10_000_000
|
364
|
+
assert !david.valid?
|
365
|
+
assert !david.save
|
366
|
+
assert_raises(AntMapper::ObjectInvalid) { david.save! }
|
367
|
+
david.destroy
|
368
|
+
end
|
369
|
+
|
370
|
+
def test_before_create_returning_false
|
371
|
+
someone = CallbackCancellationDeveloper.new
|
372
|
+
assert someone.valid?
|
373
|
+
assert !someone.save
|
374
|
+
end
|
375
|
+
|
376
|
+
def test_before_destroy_returning_false
|
377
|
+
User.create(@attributes)
|
378
|
+
david = ImmutableDeveloper.find(@attributes[:email])
|
379
|
+
|
380
|
+
assert !david.destroy
|
381
|
+
assert_not_nil ImmutableDeveloper.find(@attributes[:email])
|
382
|
+
User.find(@attributes[:email]).destroy
|
383
|
+
end
|
384
|
+
|
385
|
+
def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper
|
386
|
+
User.create(@attributes)
|
387
|
+
david = CallbackDeveloper.find(@attributes[:email])
|
388
|
+
CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :returning_false]; return false }
|
389
|
+
CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] }
|
390
|
+
david.save
|
391
|
+
assert_equal [
|
392
|
+
[ :after_initialize, :string ],
|
393
|
+
[ :after_initialize, :proc ],
|
394
|
+
[ :after_initialize, :object ],
|
395
|
+
[ :after_initialize, :block ],
|
396
|
+
[ :before_validation, :string ],
|
397
|
+
[ :before_validation, :proc ],
|
398
|
+
[ :before_validation, :object ],
|
399
|
+
[ :before_validation, :block ],
|
400
|
+
[ :before_validation, :returning_false ]
|
401
|
+
], david.history
|
402
|
+
david.destroy
|
403
|
+
end
|
404
|
+
|
405
|
+
def test_inheritence_of_callbacks
|
406
|
+
parent = ParentDeveloper.new
|
407
|
+
assert !parent.after_save_called
|
408
|
+
parent.save
|
409
|
+
assert parent.after_save_called
|
410
|
+
|
411
|
+
child = ChildDeveloper.new
|
412
|
+
assert !child.after_save_called
|
413
|
+
child.save
|
414
|
+
assert child.after_save_called
|
415
|
+
end
|
416
|
+
|
417
|
+
end
|