langalex-couch_potato 0.1
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/CREDITS +3 -0
- data/MIT-LICENSE.txt +19 -0
- data/init.rb +5 -0
- data/lib/core_ext/object.rb +5 -0
- data/lib/core_ext/time.rb +14 -0
- data/lib/couch_potato/active_record/compatibility.rb +9 -0
- data/lib/couch_potato/ordering.rb +88 -0
- data/lib/couch_potato/persistence/belongs_to_property.rb +44 -0
- data/lib/couch_potato/persistence/bulk_save_queue.rb +47 -0
- data/lib/couch_potato/persistence/callbacks.rb +96 -0
- data/lib/couch_potato/persistence/collection.rb +51 -0
- data/lib/couch_potato/persistence/external_collection.rb +54 -0
- data/lib/couch_potato/persistence/external_has_many_property.rb +68 -0
- data/lib/couch_potato/persistence/find.rb +21 -0
- data/lib/couch_potato/persistence/finder.rb +109 -0
- data/lib/couch_potato/persistence/inline_collection.rb +14 -0
- data/lib/couch_potato/persistence/inline_has_many_property.rb +39 -0
- data/lib/couch_potato/persistence/json.rb +46 -0
- data/lib/couch_potato/persistence/properties.rb +40 -0
- data/lib/couch_potato/persistence/simple_property.rb +33 -0
- data/lib/couch_potato/persistence.rb +186 -0
- data/lib/couch_potato/versioning.rb +46 -0
- data/lib/couch_potato.rb +20 -0
- data/spec/attributes_spec.rb +22 -0
- data/spec/belongs_to_spec.rb +37 -0
- data/spec/callbacks_spec.rb +229 -0
- data/spec/create_spec.rb +68 -0
- data/spec/destroy_spec.rb +24 -0
- data/spec/find_spec.rb +88 -0
- data/spec/finder_spec.rb +115 -0
- data/spec/has_many_spec.rb +178 -0
- data/spec/inline_collection_spec.rb +15 -0
- data/spec/ordering_spec.rb +94 -0
- data/spec/property_spec.rb +46 -0
- data/spec/reload_spec.rb +46 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/update_spec.rb +33 -0
- data/spec/versioning_spec.rb +149 -0
- metadata +132 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
class InlineHasManyProperty
|
2
|
+
attr_accessor :name
|
3
|
+
|
4
|
+
def initialize(owner_clazz, name, options = {})
|
5
|
+
@name = name
|
6
|
+
getter = <<-GETTER
|
7
|
+
def #{name}
|
8
|
+
@#{name} ||= CouchPotato::Persistence::InlineCollection.new(#{item_class_name})
|
9
|
+
end
|
10
|
+
GETTER
|
11
|
+
owner_clazz.class_eval getter
|
12
|
+
end
|
13
|
+
|
14
|
+
def build(object, json)
|
15
|
+
object.send("#{name}").clear
|
16
|
+
json[name.to_s].each do |item|
|
17
|
+
item.delete 'ruby_class'
|
18
|
+
object.send("#{name}").build item
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def save(object)
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def serialize(json, object)
|
27
|
+
json[name.to_s] = object.send(name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy(object)
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def item_class_name
|
37
|
+
@name.to_s.singularize.camelcase
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module Persistence
|
3
|
+
module Json
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_json(*args)
|
9
|
+
(self.class.properties).inject({}) do |props, property|
|
10
|
+
property.serialize(props, self)
|
11
|
+
props
|
12
|
+
end.merge('ruby_class' => self.class.name).merge(id_and_rev_json).merge(timestamps_json).to_json(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def id_and_rev_json
|
18
|
+
[:_id, :_rev, :_deleted].inject({}) do |hash, key|
|
19
|
+
hash[key] = self.send(key) unless self.send(key).nil?
|
20
|
+
hash
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def timestamps_json
|
25
|
+
[:created_at, :updated_at].inject({}) do |hash, key|
|
26
|
+
hash[key] = self.send(key).to_s unless self.send(key).nil?
|
27
|
+
hash
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
def json_create(json)
|
33
|
+
instance = self.new
|
34
|
+
instance.created_at = Time.parse(json['created_at'])
|
35
|
+
instance.updated_at = Time.parse(json['updated_at'])
|
36
|
+
instance._id = json['_id']
|
37
|
+
instance._rev = json['_rev']
|
38
|
+
properties.each do |property|
|
39
|
+
property.build(instance, json)
|
40
|
+
end
|
41
|
+
instance
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/simple_property'
|
2
|
+
require File.dirname(__FILE__) + '/belongs_to_property'
|
3
|
+
require File.dirname(__FILE__) + '/inline_has_many_property'
|
4
|
+
require File.dirname(__FILE__) + '/external_has_many_property'
|
5
|
+
|
6
|
+
module CouchPotato
|
7
|
+
module Persistence
|
8
|
+
module Properties
|
9
|
+
def self.included(base)
|
10
|
+
base.extend ClassMethods
|
11
|
+
base.class_eval do
|
12
|
+
def self.properties
|
13
|
+
@@properties ||= {}
|
14
|
+
@@properties[self.name] ||= []
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
def property_names
|
21
|
+
properties.map(&:name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def property(name, options = {})
|
25
|
+
clazz = options.delete(:class)
|
26
|
+
properties << (clazz || SimpleProperty).new(self, name, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def belongs_to(name)
|
30
|
+
property name, :class => BelongsToProperty
|
31
|
+
end
|
32
|
+
|
33
|
+
def has_many(name, options = {})
|
34
|
+
stored = options.delete(:stored)
|
35
|
+
property name, options.merge(:class => (stored == :inline ? InlineHasManyProperty : ExternalHasManyProperty))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module Persistence
|
3
|
+
class SimpleProperty
|
4
|
+
attr_accessor :name
|
5
|
+
|
6
|
+
def initialize(owner_clazz, name, options = {})
|
7
|
+
self.name = name
|
8
|
+
owner_clazz.class_eval do
|
9
|
+
attr_accessor name
|
10
|
+
define_method "#{name}?" do
|
11
|
+
!self.send(name).nil? && !self.send(name).try(:blank?)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def build(object, json)
|
17
|
+
object.send "#{name}=", json.stringify_keys[name.to_s]
|
18
|
+
end
|
19
|
+
|
20
|
+
def save(object)
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def destroy(object)
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def serialize(json, object)
|
29
|
+
json[name] = object.send name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'couchrest'
|
3
|
+
require 'validatable'
|
4
|
+
require File.dirname(__FILE__) + '/persistence/inline_collection'
|
5
|
+
require File.dirname(__FILE__) + '/persistence/external_collection'
|
6
|
+
require File.dirname(__FILE__) + '/persistence/properties'
|
7
|
+
require File.dirname(__FILE__) + '/persistence/callbacks'
|
8
|
+
require File.dirname(__FILE__) + '/persistence/json'
|
9
|
+
require File.dirname(__FILE__) + '/persistence/bulk_save_queue'
|
10
|
+
require File.dirname(__FILE__) + '/persistence/find'
|
11
|
+
|
12
|
+
module CouchPotato
|
13
|
+
module Persistence
|
14
|
+
|
15
|
+
class ValidationsFailedError < ::Exception; end
|
16
|
+
class UnsavedRecordError < ::Exception; end
|
17
|
+
|
18
|
+
def self.included(base)
|
19
|
+
base.send :extend, ClassMethods, Find
|
20
|
+
base.send :include, Callbacks, Properties, Validatable, Json
|
21
|
+
base.class_eval do
|
22
|
+
attr_accessor :_id, :_rev, :_attachments, :_deleted, :created_at, :updated_at
|
23
|
+
attr_reader :bulk_save_queue
|
24
|
+
alias_method :id, :_id
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(attributes = {})
|
29
|
+
@bulk_save_queue = BulkSaveQueue.new
|
30
|
+
attributes.each do |name, value|
|
31
|
+
self.send("#{name}=", value)
|
32
|
+
end if attributes
|
33
|
+
end
|
34
|
+
|
35
|
+
def attributes=(hash)
|
36
|
+
hash.each do |attribute, value|
|
37
|
+
self.send "#{attribute}=", value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def attributes
|
42
|
+
self.class.properties.inject({}) do |res, property|
|
43
|
+
property.serialize(res, self)
|
44
|
+
res
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def save!
|
49
|
+
save || raise(ValidationsFailedError.new(self.errors.full_messages))
|
50
|
+
end
|
51
|
+
|
52
|
+
def save
|
53
|
+
if new_document?
|
54
|
+
create_document
|
55
|
+
else
|
56
|
+
update_document
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def destroy
|
61
|
+
run_callbacks(:before_destroy)
|
62
|
+
self._deleted = true
|
63
|
+
bulk_save_queue << self
|
64
|
+
destroy_dependent_objects
|
65
|
+
bulk_save_queue.save do |res|
|
66
|
+
self._id = nil
|
67
|
+
self._rev = nil
|
68
|
+
end
|
69
|
+
run_callbacks(:after_destroy)
|
70
|
+
end
|
71
|
+
|
72
|
+
def reload
|
73
|
+
raise(UnsavedRecordError.new) unless _id
|
74
|
+
json = self.class.db.get _id
|
75
|
+
self.class.properties.each do |property|
|
76
|
+
property.build self, json
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def new_document?
|
81
|
+
_id.nil?
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_param
|
85
|
+
_id
|
86
|
+
end
|
87
|
+
|
88
|
+
def [](name)
|
89
|
+
self.send name
|
90
|
+
end
|
91
|
+
|
92
|
+
def ==(other)
|
93
|
+
other.class == self.class && self.class.property_names.map{|name| self.send(name)} == self.class.property_names.map{|name| other.send(name)}
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def create_document
|
99
|
+
run_callbacks :before_validation_on_save
|
100
|
+
run_callbacks :before_validation_on_create
|
101
|
+
return unless valid?
|
102
|
+
run_callbacks :before_save
|
103
|
+
run_callbacks :before_create
|
104
|
+
self.created_at = Time.now
|
105
|
+
self.updated_at = Time.now
|
106
|
+
self._id = self.class.db.server.next_uuid rescue Digest::MD5.hexdigest(rand(1000000000000).to_s) # only works with couchdb 0.9
|
107
|
+
bulk_save_queue << self
|
108
|
+
save_dependent_objects
|
109
|
+
bulk_save_queue.save do |res|
|
110
|
+
self._rev = extract_rev(res)
|
111
|
+
end
|
112
|
+
run_callbacks :after_save
|
113
|
+
run_callbacks :after_create
|
114
|
+
true
|
115
|
+
end
|
116
|
+
|
117
|
+
def extract_rev(res)
|
118
|
+
res['new_revs'].select{|hash| hash['id'] == self.id}.first['rev']
|
119
|
+
end
|
120
|
+
|
121
|
+
def update_document
|
122
|
+
run_callbacks(:before_validation_on_save)
|
123
|
+
run_callbacks(:before_validation_on_update)
|
124
|
+
return unless valid?
|
125
|
+
run_callbacks :before_save
|
126
|
+
run_callbacks :before_update
|
127
|
+
self.updated_at = Time.now
|
128
|
+
bulk_save_queue << self
|
129
|
+
save_dependent_objects
|
130
|
+
bulk_save_queue.save do |res|
|
131
|
+
self._rev = extract_rev(res)
|
132
|
+
end
|
133
|
+
run_callbacks :after_save
|
134
|
+
run_callbacks :after_update
|
135
|
+
true
|
136
|
+
end
|
137
|
+
|
138
|
+
def save_dependent_objects
|
139
|
+
self.class.properties.each do |property|
|
140
|
+
property.save(self)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def destroy_dependent_objects
|
145
|
+
self.class.properties.each do |property|
|
146
|
+
property.destroy(self)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
module ClassMethods
|
151
|
+
|
152
|
+
def create!(attributes = {})
|
153
|
+
instance = self.new attributes
|
154
|
+
instance.save!
|
155
|
+
instance
|
156
|
+
end
|
157
|
+
|
158
|
+
def create(attributes = {})
|
159
|
+
instance = self.new attributes
|
160
|
+
instance.save
|
161
|
+
instance
|
162
|
+
end
|
163
|
+
|
164
|
+
def get(id)
|
165
|
+
begin
|
166
|
+
self.json_create db.get(id)
|
167
|
+
rescue(RestClient::ResourceNotFound)
|
168
|
+
nil
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def db(name = nil)
|
173
|
+
::CouchPotato::Persistence.Db(name)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.Db(database_name = nil)
|
178
|
+
database_name ||= CouchPotato::Config.database_name || raise('No Database configured. Set CouchPotato::Config.database_name')
|
179
|
+
full_url_to_database = database_name
|
180
|
+
if full_url_to_database !~ /^http:\/\//
|
181
|
+
full_url_to_database = "http://localhost:5984/#{database_name}"
|
182
|
+
end
|
183
|
+
CouchRest.database!(full_url_to_database)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module Versioning
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
property :version
|
6
|
+
property :master_version_id
|
7
|
+
cattr_accessor :new_version_condition
|
8
|
+
before_create :set_version_default
|
9
|
+
before_update :prepare_for_new_version
|
10
|
+
|
11
|
+
def self.set_version_condition(lambda)
|
12
|
+
self.new_version_condition = lambda
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def versions(version_no = nil)
|
18
|
+
if version_no
|
19
|
+
CouchPotato::Persistence::Finder.new.find(self.class, :version => version_no).first
|
20
|
+
elsif version == 1
|
21
|
+
[self]
|
22
|
+
else
|
23
|
+
CouchPotato::Persistence::Finder.new.find(self.class, :master_version_id => _id).sort_by(&:version)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def set_version_default
|
30
|
+
self.version ||= 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def prepare_for_new_version
|
34
|
+
if new_version_condition.nil? || new_version_condition.call(self)
|
35
|
+
copy = self.class.get self._id
|
36
|
+
copy._id = nil
|
37
|
+
copy._rev = nil
|
38
|
+
copy.master_version_id = self._id
|
39
|
+
copy.save
|
40
|
+
self.master_version_id ||= self.id
|
41
|
+
self.version += 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/lib/couch_potato.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
require 'json'
|
4
|
+
require 'json/add/core'
|
5
|
+
require 'json/add/rails'
|
6
|
+
|
7
|
+
require 'ostruct'
|
8
|
+
|
9
|
+
module CouchPotato
|
10
|
+
Config = OpenStruct.new
|
11
|
+
end
|
12
|
+
|
13
|
+
require File.dirname(__FILE__) + '/core_ext/object'
|
14
|
+
require File.dirname(__FILE__) + '/core_ext/time'
|
15
|
+
|
16
|
+
require File.dirname(__FILE__) + '/couch_potato/persistence'
|
17
|
+
require File.dirname(__FILE__) + '/couch_potato/versioning'
|
18
|
+
require File.dirname(__FILE__) + '/couch_potato/ordering'
|
19
|
+
require File.dirname(__FILE__) + '/couch_potato/active_record/compatibility'
|
20
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe 'attributes=' do
|
4
|
+
|
5
|
+
class Plant
|
6
|
+
include CouchPotato::Persistence
|
7
|
+
property :leaf_count
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should assign the attributes" do
|
11
|
+
plant = Plant.new
|
12
|
+
plant.attributes = {:leaf_count => 1}
|
13
|
+
plant.leaf_count.should == 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "attributes" do
|
18
|
+
it "should return the attributes" do
|
19
|
+
plant = Plant.new :leaf_count => 1
|
20
|
+
plant.attributes .should == {:leaf_count => 1}
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe 'belongs_to' do
|
4
|
+
before(:each) do
|
5
|
+
@commenter = Commenter.create!
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should return nil by default" do
|
9
|
+
c = Comment.new :title => 'title'
|
10
|
+
c.commenter.should be_nil
|
11
|
+
c.commenter_id.should be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should assign the parent object" do
|
15
|
+
c = Comment.new :title => 'title'
|
16
|
+
c.commenter = @commenter
|
17
|
+
c.commenter.should == @commenter
|
18
|
+
c.commenter_id.should == @commenter.id
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should assign the parent object id" do
|
22
|
+
c = Comment.new :title => 'title'
|
23
|
+
c.commenter_id = @commenter.id
|
24
|
+
c.commenter.should == @commenter
|
25
|
+
c.commenter_id.should == @commenter.id
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should persist the link to the parent object" do
|
29
|
+
c = Comment.new :title => 'title'
|
30
|
+
c.commenter_id = @commenter.id
|
31
|
+
c.save!
|
32
|
+
c = Comment.find c.id
|
33
|
+
c.commenter._id.should == @commenter.id
|
34
|
+
c.commenter_id.should == @commenter._id
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
class CallbackRecorder
|
4
|
+
include CouchPotato::Persistence
|
5
|
+
|
6
|
+
property :required_property
|
7
|
+
|
8
|
+
validates_presence_of :required_property
|
9
|
+
|
10
|
+
[:before_validation_on_create,
|
11
|
+
:before_validation_on_save, :before_validation_on_update,
|
12
|
+
:before_save, :before_create, :before_create,
|
13
|
+
:after_save, :after_create, :after_create,
|
14
|
+
:before_update, :after_update,
|
15
|
+
:before_destroy, :after_destroy
|
16
|
+
].each do |callback|
|
17
|
+
define_method callback do
|
18
|
+
callbacks << callback
|
19
|
+
end
|
20
|
+
self.send callback, callback
|
21
|
+
end
|
22
|
+
|
23
|
+
def callbacks
|
24
|
+
@callbacks ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "multiple callbacks at once" do
|
30
|
+
class Monkey
|
31
|
+
include CouchPotato::Persistence
|
32
|
+
attr_accessor :eaten_banana, :eaten_apple
|
33
|
+
|
34
|
+
before_create :eat_apple, :eat_banana
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def eat_banana
|
39
|
+
self.eaten_banana = true
|
40
|
+
end
|
41
|
+
|
42
|
+
def eat_apple
|
43
|
+
self.eaten_apple = true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
it "should run all callback methods given to the callback method call" do
|
47
|
+
monkey = Monkey.create!
|
48
|
+
monkey.eaten_banana.should be_true
|
49
|
+
monkey.eaten_apple.should be_true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'create callbacks' do
|
54
|
+
|
55
|
+
before(:each) do
|
56
|
+
@recorder = CallbackRecorder.new
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "successful create" do
|
60
|
+
before(:each) do
|
61
|
+
@recorder.required_property = 1
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should call before_validation_on_create" do
|
65
|
+
@recorder.save!
|
66
|
+
@recorder.callbacks.should include(:before_validation_on_create)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should call before_validation_on_save" do
|
70
|
+
@recorder.save!
|
71
|
+
@recorder.callbacks.should include(:before_validation_on_save)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should call before_save" do
|
75
|
+
@recorder.save!
|
76
|
+
@recorder.callbacks.should include(:before_save)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should call after_save" do
|
80
|
+
@recorder.save!
|
81
|
+
@recorder.callbacks.should include(:after_save)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should call before_create" do
|
85
|
+
@recorder.save!
|
86
|
+
@recorder.callbacks.should include(:before_create)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should call after_create" do
|
90
|
+
@recorder.save!
|
91
|
+
@recorder.callbacks.should include(:after_create)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "failed create" do
|
97
|
+
|
98
|
+
it "should call before_validation_on_create" do
|
99
|
+
@recorder.save
|
100
|
+
@recorder.callbacks.should include(:before_validation_on_create)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should call before_validation_on_save" do
|
104
|
+
@recorder.save
|
105
|
+
@recorder.callbacks.should include(:before_validation_on_save)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should not call before_save" do
|
109
|
+
@recorder.save
|
110
|
+
@recorder.callbacks.should_not include(:before_save)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should not call after_save" do
|
114
|
+
@recorder.save
|
115
|
+
@recorder.callbacks.should_not include(:after_save)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should not call before_create" do
|
119
|
+
@recorder.save
|
120
|
+
@recorder.callbacks.should_not include(:before_create)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should not call after_create" do
|
124
|
+
@recorder.save
|
125
|
+
@recorder.callbacks.should_not include(:after_create)
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "update callbacks" do
|
134
|
+
|
135
|
+
before(:each) do
|
136
|
+
@recorder = CallbackRecorder.create! :required_property => 1
|
137
|
+
@recorder.callbacks.clear
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "successful update" do
|
141
|
+
|
142
|
+
it "should call before_validation_on_update" do
|
143
|
+
@recorder.save!
|
144
|
+
@recorder.callbacks.should include(:before_validation_on_update)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should call before_validation_on_save" do
|
148
|
+
@recorder.save!
|
149
|
+
@recorder.callbacks.should include(:before_validation_on_save)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should call before_save" do
|
153
|
+
@recorder.save!
|
154
|
+
@recorder.callbacks.should include(:before_save)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should call after_save" do
|
158
|
+
@recorder.save!
|
159
|
+
@recorder.callbacks.should include(:after_save)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should call before_update" do
|
163
|
+
@recorder.save!
|
164
|
+
@recorder.callbacks.should include(:before_update)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should call after_update" do
|
168
|
+
@recorder.save!
|
169
|
+
@recorder.callbacks.should include(:after_update)
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "failed update" do
|
175
|
+
|
176
|
+
before(:each) do
|
177
|
+
@recorder.required_property = nil
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should call before_validation_on_update" do
|
181
|
+
@recorder.save
|
182
|
+
@recorder.callbacks.should include(:before_validation_on_update)
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should call before_validation_on_save" do
|
186
|
+
@recorder.save
|
187
|
+
@recorder.callbacks.should include(:before_validation_on_save)
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should not call before_save" do
|
191
|
+
@recorder.save
|
192
|
+
@recorder.callbacks.should_not include(:before_save)
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should not call after_save" do
|
196
|
+
@recorder.save
|
197
|
+
@recorder.callbacks.should_not include(:after_save)
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should not call before_update" do
|
201
|
+
@recorder.save
|
202
|
+
@recorder.callbacks.should_not include(:before_update)
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should not call after_update" do
|
206
|
+
@recorder.save
|
207
|
+
@recorder.callbacks.should_not include(:after_update)
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "destroy callbacks" do
|
215
|
+
before(:each) do
|
216
|
+
@recorder = CallbackRecorder.create! :required_property => 1
|
217
|
+
@recorder.callbacks.clear
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should call before_destroy" do
|
221
|
+
@recorder.destroy
|
222
|
+
@recorder.callbacks.should include(:before_destroy)
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should call after_destroy" do
|
226
|
+
@recorder.destroy
|
227
|
+
@recorder.callbacks.should include(:after_destroy)
|
228
|
+
end
|
229
|
+
end
|