couch_tomato 0.1.0
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/MIT-LICENSE.txt +19 -0
- data/README.md +96 -0
- data/init.rb +3 -0
- data/lib/core_ext/date.rb +10 -0
- data/lib/core_ext/duplicable.rb +43 -0
- data/lib/core_ext/extract_options.rb +14 -0
- data/lib/core_ext/inheritable_attributes.rb +222 -0
- data/lib/core_ext/object.rb +5 -0
- data/lib/core_ext/string.rb +19 -0
- data/lib/core_ext/symbol.rb +15 -0
- data/lib/core_ext/time.rb +12 -0
- data/lib/couch_tomato/database.rb +279 -0
- data/lib/couch_tomato/js_view_source.rb +182 -0
- data/lib/couch_tomato/migration.rb +52 -0
- data/lib/couch_tomato/migrator.rb +235 -0
- data/lib/couch_tomato/persistence/base.rb +62 -0
- data/lib/couch_tomato/persistence/belongs_to_property.rb +58 -0
- data/lib/couch_tomato/persistence/callbacks.rb +60 -0
- data/lib/couch_tomato/persistence/dirty_attributes.rb +27 -0
- data/lib/couch_tomato/persistence/json.rb +48 -0
- data/lib/couch_tomato/persistence/magic_timestamps.rb +15 -0
- data/lib/couch_tomato/persistence/properties.rb +58 -0
- data/lib/couch_tomato/persistence/simple_property.rb +97 -0
- data/lib/couch_tomato/persistence/validation.rb +18 -0
- data/lib/couch_tomato/persistence.rb +85 -0
- data/lib/couch_tomato/replicator.rb +50 -0
- data/lib/couch_tomato.rb +46 -0
- data/lib/tasks/couch_tomato.rake +128 -0
- data/rails/init.rb +7 -0
- data/spec/callbacks_spec.rb +271 -0
- data/spec/comment.rb +8 -0
- data/spec/create_spec.rb +22 -0
- data/spec/custom_view_spec.rb +134 -0
- data/spec/destroy_spec.rb +29 -0
- data/spec/fixtures/address.rb +9 -0
- data/spec/fixtures/person.rb +6 -0
- data/spec/property_spec.rb +103 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/unit/attributes_spec.rb +26 -0
- data/spec/unit/callbacks_spec.rb +33 -0
- data/spec/unit/create_spec.rb +58 -0
- data/spec/unit/customs_views_spec.rb +15 -0
- data/spec/unit/database_spec.rb +38 -0
- data/spec/unit/dirty_attributes_spec.rb +113 -0
- data/spec/unit/string_spec.rb +13 -0
- data/spec/unit/view_query_spec.rb +9 -0
- data/spec/update_spec.rb +40 -0
- data/test/test_helper.rb +63 -0
- data/test/unit/database_test.rb +285 -0
- data/test/unit/js_view_test.rb +362 -0
- data/test/unit/property_test.rb +193 -0
- metadata +133 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require File.dirname(__FILE__) + '/database'
|
3
|
+
require File.dirname(__FILE__) + '/persistence/properties'
|
4
|
+
require File.dirname(__FILE__) + '/persistence/base'
|
5
|
+
require File.dirname(__FILE__) + '/persistence/magic_timestamps'
|
6
|
+
require File.dirname(__FILE__) + '/persistence/callbacks'
|
7
|
+
require File.dirname(__FILE__) + '/persistence/json'
|
8
|
+
require File.dirname(__FILE__) + '/persistence/dirty_attributes'
|
9
|
+
require File.dirname(__FILE__) + '/persistence/validation'
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
module CouchTomato
|
14
|
+
module Persistence
|
15
|
+
module Nested
|
16
|
+
include CouchTomato::Persistence::Base
|
17
|
+
|
18
|
+
def self.included(base)
|
19
|
+
base.send :include, Properties, Callbacks, Validation#, Json#, CouchTomato::View::CustomViews
|
20
|
+
# base.send :include, DirtyAttributes
|
21
|
+
# base.send :include, MagicTimestamps
|
22
|
+
|
23
|
+
base.extend ClassMethods
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_json(*args)
|
27
|
+
to_hash.to_json(*args)
|
28
|
+
# to_json(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
# returns all the attributes, the ruby class and the _id and _rev of a model as a Hash
|
32
|
+
def to_hash
|
33
|
+
(self.class.properties).inject({}) do |props, property|
|
34
|
+
property.serialize(props, self)
|
35
|
+
props
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
# creates a model instance from JSON
|
43
|
+
def json_create(json, meta={})
|
44
|
+
return if json.nil?
|
45
|
+
instance = self.new
|
46
|
+
# instance._id = json[:_id] || json['_id']
|
47
|
+
# instance._rev = json[:_rev] || json['_rev']
|
48
|
+
properties.each do |property|
|
49
|
+
property.build(instance, json)
|
50
|
+
end
|
51
|
+
instance
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
include CouchTomato::Persistence::Base
|
58
|
+
|
59
|
+
def self.included(base)
|
60
|
+
base.send :include, Properties, Callbacks, Validation, Json#, CouchTomato::View::CustomViews
|
61
|
+
# base.send :include, DirtyAttributes
|
62
|
+
base.send :include, MagicTimestamps
|
63
|
+
base.class_eval do
|
64
|
+
attr_accessor :_id, :_rev, :_attachments, :_deleted
|
65
|
+
attr_accessor :metadata
|
66
|
+
alias_method :id, :_id
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# returns true if a model hasn't been saved yet, false otherwise
|
71
|
+
def new?
|
72
|
+
_rev.nil?
|
73
|
+
end
|
74
|
+
alias_method :new_record?, :new?
|
75
|
+
|
76
|
+
# returns the document id
|
77
|
+
# this is used by rails to construct URLs
|
78
|
+
# can be overridden to for example use slugs for URLs instead if ids
|
79
|
+
def to_param
|
80
|
+
_id
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module CouchTomato
|
2
|
+
class Replicator
|
3
|
+
# Timeout for a single database replication.
|
4
|
+
READ_TIMEOUT = 24 * 60 * 60 # 24 hours in seconds
|
5
|
+
|
6
|
+
def initialize(src_server, dst_server = nil)
|
7
|
+
@src_server = CouchRest::Server.new(src_server)
|
8
|
+
@dst_server = dst_server ? CouchRest::Server.new(dst_server) : @src_server
|
9
|
+
|
10
|
+
@db_names = @src_server.databases
|
11
|
+
end
|
12
|
+
|
13
|
+
def replicate(src_db_name, dst_db_name)
|
14
|
+
raise "Source database '#{src_db_name}' does not exist" unless @db_names.include?(src_db_name)
|
15
|
+
|
16
|
+
@dst_server.database!(dst_db_name)
|
17
|
+
|
18
|
+
src_uri = URI.parse(@src_server.uri)
|
19
|
+
dst_uri = URI.parse(@dst_server.uri)
|
20
|
+
|
21
|
+
http = Net::HTTP.new(dst_uri.host, dst_uri.port)
|
22
|
+
http.read_timeout = READ_TIMEOUT
|
23
|
+
http.post('/_replicate', "{\"source\": \"#{src_uri}/#{src_db_name}\", \"target\": \"#{dst_uri}/#{dst_db_name}\"}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def replicate_all(suffix = nil)
|
27
|
+
@db_names.each do |db_name|
|
28
|
+
replicate(db_name, "#{db_name}#{suffix}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def replicate_env!(from_env, to_env, prefix=nil)
|
33
|
+
source_dbs = @db_names.select do |e|
|
34
|
+
if prefix
|
35
|
+
e =~ /^#{prefix}_/ && e =~ /_#{from_env}$/
|
36
|
+
else
|
37
|
+
e =~ /_#{from_env}$/
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
source_dbs.each do |source_db|
|
42
|
+
target_db = source_db.gsub(/_#{from_env}$/, "_#{to_env}")
|
43
|
+
|
44
|
+
puts "Recreating #{target_db}"
|
45
|
+
CouchRest::Database.new(@dst_server, target_db).recreate!
|
46
|
+
replicate(source_db, target_db)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/couch_tomato.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'couchrest'
|
2
|
+
require 'json'
|
3
|
+
require 'json/add/core'
|
4
|
+
require 'json/add/rails'
|
5
|
+
|
6
|
+
# require 'ostruct'
|
7
|
+
|
8
|
+
|
9
|
+
module CouchTomato
|
10
|
+
# Config = OpenStruct.new
|
11
|
+
|
12
|
+
# Returns a database instance which you can then use to create objects and query views.
|
13
|
+
# You have to set the CouchTomato::Config.database_name before this works.
|
14
|
+
|
15
|
+
# def self.database
|
16
|
+
# @@__database ||= Database.new(self.couchrest_database)
|
17
|
+
# end
|
18
|
+
|
19
|
+
# Returns the underlying CouchRest database object if you want low level access to your CouchDB.
|
20
|
+
# You have to set the CouchTomato::Config.database_name before this works.
|
21
|
+
# def self.couchrest_database
|
22
|
+
# @@__couchrest_database ||= CouchRest.database(full_url_to_database)
|
23
|
+
# end
|
24
|
+
|
25
|
+
# private
|
26
|
+
|
27
|
+
# def self.full_url_to_database
|
28
|
+
# raise('No Database configured. Set CouchTomato::Config.database_name') unless CouchTomato::Config.database_name
|
29
|
+
# if CouchTomato::Config.database_server
|
30
|
+
# return "#{CouchTomato::Config.database_server}#{CouchTomato::Config.database_name}"
|
31
|
+
# else
|
32
|
+
# return "http://127.0.0.1:5984/#{CouchTomato::Config.database_name}"
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
end
|
36
|
+
|
37
|
+
require File.dirname(__FILE__) + '/core_ext/object'
|
38
|
+
require File.dirname(__FILE__) + '/core_ext/time'
|
39
|
+
require File.dirname(__FILE__) + '/core_ext/date'
|
40
|
+
require File.dirname(__FILE__) + '/core_ext/string'
|
41
|
+
require File.dirname(__FILE__) + '/core_ext/symbol'
|
42
|
+
require File.dirname(__FILE__) + '/core_ext/extract_options'
|
43
|
+
require File.dirname(__FILE__) + '/core_ext/duplicable'
|
44
|
+
require File.dirname(__FILE__) + '/core_ext/inheritable_attributes'
|
45
|
+
require File.dirname(__FILE__) + '/couch_tomato/persistence'
|
46
|
+
require File.dirname(__FILE__) + '/couch_tomato/js_view_source'
|
@@ -0,0 +1,128 @@
|
|
1
|
+
namespace :couch_tomato do
|
2
|
+
desc 'Inserts the views into CouchDB'
|
3
|
+
task :push => :environment do
|
4
|
+
CouchTomato::JsViewSource.push
|
5
|
+
end
|
6
|
+
|
7
|
+
desc 'Compares views in DB and the File System'
|
8
|
+
task :diff => :environment do
|
9
|
+
CouchTomato::JsViewSource.diff
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Drops databases for the current RAILS_ENV'
|
13
|
+
task :drop => :environment do
|
14
|
+
databases do |db, dir|
|
15
|
+
db.delete!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Runs migrations'
|
20
|
+
task :migrate => :environment do
|
21
|
+
databases do |db, dir|
|
22
|
+
CouchTomato::Migrator.migrate(db, dir, ENV['VERSION'] ? ENV['VERSION'].to_i : nil)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
namespace :migrate do
|
27
|
+
desc 'Rollbacks the database one migration and re migrate up. If you want to rollback more than one step, define STEP=x. Target specific version with VERSION=x.'
|
28
|
+
task :redo => :environment do
|
29
|
+
if ENV['VERSION']
|
30
|
+
Rake::Task['couch_tomato:migrate:down'].invoke
|
31
|
+
Rake::Task['couch_tomato:migrate:up'].invoke
|
32
|
+
else
|
33
|
+
Rake::Task['couch_tomato:rollback'].invoke
|
34
|
+
Rake::Task['couch_tomato:migrate'].invoke
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'Resets your database using your migrations for the current environment'
|
39
|
+
task :reset => ['couch_tomato:drop', 'couch_tomato:push', 'couch_tomato:migrate']
|
40
|
+
|
41
|
+
desc 'Runs the "up" for a given migration VERSION.'
|
42
|
+
task :up => :environment do
|
43
|
+
version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
|
44
|
+
raise 'VERSION is required' unless version
|
45
|
+
|
46
|
+
databases do |db, dir|
|
47
|
+
CouchTomato::Migrator.run(:up, db, dir, version)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
desc 'Runs the "down" for a given migration VERSION.'
|
52
|
+
task :down => :environment do
|
53
|
+
version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
|
54
|
+
raise 'VERSION is required' unless version
|
55
|
+
|
56
|
+
databases do |db, dir|
|
57
|
+
CouchTomato::Migrator.run(:down, db, dir, version)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
desc 'Rolls back to the previous version. Specify the number of steps with STEP=n'
|
63
|
+
task :rollback => :environment do
|
64
|
+
databases do |db, dir|
|
65
|
+
CouchTomato::Migrator.rollback(db, dir, ENV['STEP'] ? ENV['STEP'].to_i : 1)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
desc 'Rolls forward to the next version. Specify the number of steps with STEP=n'
|
70
|
+
task :forward => :environment do
|
71
|
+
databases do |db, dir|
|
72
|
+
CouchTomato::Migrator.forward(db, dir, ENV['STEP'] ? ENV['STEP'].to_i : 1)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
desc 'Replicates couch databases'
|
77
|
+
task :replicate => :environment do
|
78
|
+
src_server, dst_server = servers
|
79
|
+
|
80
|
+
src_db = ENV['DB']
|
81
|
+
dst_db = ENV['DST_DB'] || (src_server == dst_server ? "#{src_db}_bak" : src_db)
|
82
|
+
|
83
|
+
replicator = CouchTomato::Replicator.new(src_server, dst_server)
|
84
|
+
|
85
|
+
if src_db
|
86
|
+
puts "== Replicating '#{src_server}/#{src_db}' to '#{dst_server}/#{dst_db}'"
|
87
|
+
replicator.replicate(src_db, dst_db)
|
88
|
+
elsif src_server == dst_server
|
89
|
+
puts "== Replicating all databases at '#{src_server}' using '_bak' suffix for replicated database names"
|
90
|
+
replicator.replicate_all('_bak')
|
91
|
+
else
|
92
|
+
puts "== Replicating all databases from '#{src_server}' to '#{dst_server}'"
|
93
|
+
replicator.replicate_all
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
namespace :replicate do
|
98
|
+
desc 'Replicate databases between app environments'
|
99
|
+
task :env => :environment do
|
100
|
+
src_server, dst_server = servers
|
101
|
+
|
102
|
+
src_env = ENV['SRC_ENV'] || 'production'
|
103
|
+
dst_env = ENV['DST_ENV'] || 'development'
|
104
|
+
|
105
|
+
replicator = CouchTomato::Replicator.new(src_server, dst_server)
|
106
|
+
replicator.replicate_env(src_env, dst_env, ENV['PREFIX'])
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def servers
|
113
|
+
local_server = "http://#{APP_CONFIG['couchdb_address']}:#{APP_CONFIG['couchdb_port']}"
|
114
|
+
src_server = (ENV['SRC_SERVER'] || local_server).gsub(/\s*\/\s*$/, '')
|
115
|
+
dst_server = (ENV['DST_SERVER'] || local_server).gsub(/\s*\/\s*$/, '')
|
116
|
+
|
117
|
+
return src_server, dst_server
|
118
|
+
end
|
119
|
+
|
120
|
+
def databases
|
121
|
+
dirs = ENV['DB'] ? ["couchdb/migrate/#{ENV['DB']}"] : Dir['couchdb/migrate/*']
|
122
|
+
dirs.each do |dir|
|
123
|
+
db_name = File.basename(dir)
|
124
|
+
db = CouchTomato::JsViewSource.database!(db_name)
|
125
|
+
yield db, dir
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# this is for rails only
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../lib/couch_tomato'
|
4
|
+
|
5
|
+
# CouchTomato::Config.database_name = YAML::load(File.read(Rails.root.to_s + '/config/couchdb.yml'))[RAILS_ENV]
|
6
|
+
|
7
|
+
RAILS_DEFAULT_LOGGER.info "** couch_tomato: initialized from #{__FILE__}"
|
@@ -0,0 +1,271 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
class CallbackRecorder
|
4
|
+
include CouchTomato::Persistence
|
5
|
+
|
6
|
+
property :required_property
|
7
|
+
|
8
|
+
validates_presence_of :required_property
|
9
|
+
|
10
|
+
[:before_validation, :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
|
+
view :all, :key => :required_property
|
24
|
+
|
25
|
+
attr_accessor :lambda_works
|
26
|
+
before_create lambda {|model| model.lambda_works = true }
|
27
|
+
|
28
|
+
def callbacks
|
29
|
+
@callbacks ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def method_callback_with_argument(db)
|
35
|
+
db.view CallbackRecorder.all
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "multiple callbacks at once" do
|
41
|
+
|
42
|
+
class Monkey
|
43
|
+
include CouchTomato::Persistence
|
44
|
+
attr_accessor :eaten_banana, :eaten_apple
|
45
|
+
|
46
|
+
before_create :eat_apple, :eat_banana
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def eat_banana
|
51
|
+
self.eaten_banana = true
|
52
|
+
end
|
53
|
+
|
54
|
+
def eat_apple
|
55
|
+
self.eaten_apple = true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
it "should run all callback methods given to the callback method call" do
|
59
|
+
monkey = Monkey.new
|
60
|
+
CouchTomato.database.save_document! monkey
|
61
|
+
monkey.eaten_banana.should be_true
|
62
|
+
monkey.eaten_apple.should be_true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'create callbacks' do
|
67
|
+
|
68
|
+
before(:each) do
|
69
|
+
@recorder = CallbackRecorder.new
|
70
|
+
couchrest_database = stub 'couchrest_database', :save_doc => {'id' => '1', 'rev' => '2'}, :view => {'rows' => []}, :info => nil
|
71
|
+
@db = CouchTomato::Database.new(couchrest_database)
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "successful create" do
|
75
|
+
before(:each) do
|
76
|
+
@recorder.required_property = 1
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should call before_validation" do
|
80
|
+
@recorder.valid?
|
81
|
+
@recorder.callbacks.should include(:before_validation)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should call before_validation_on_create" do
|
85
|
+
@db.save_document! @recorder
|
86
|
+
@recorder.callbacks.should include(:before_validation_on_create)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should call before_validation_on_save" do
|
90
|
+
@db.save_document! @recorder
|
91
|
+
@recorder.callbacks.should include(:before_validation_on_save)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should call before_save" do
|
95
|
+
@db.save_document! @recorder
|
96
|
+
@recorder.callbacks.should include(:before_save)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should call after_save" do
|
100
|
+
@db.save_document! @recorder
|
101
|
+
@recorder.callbacks.should include(:after_save)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should call before_create" do
|
105
|
+
@db.save_document! @recorder
|
106
|
+
@recorder.callbacks.should include(:before_create)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should call after_create" do
|
110
|
+
@db.save_document! @recorder
|
111
|
+
@recorder.callbacks.should include(:after_create)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "failed create" do
|
117
|
+
|
118
|
+
it "should call before_validation" do
|
119
|
+
@recorder.valid?
|
120
|
+
@recorder.callbacks.should include(:before_validation)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should call before_validation_on_create" do
|
124
|
+
@db.save_document @recorder
|
125
|
+
@recorder.callbacks.should include(:before_validation_on_create)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should call before_validation_on_save" do
|
129
|
+
@db.save_document @recorder
|
130
|
+
@recorder.callbacks.should include(:before_validation_on_save)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should not call before_save" do
|
134
|
+
@db.save_document @recorder
|
135
|
+
@recorder.callbacks.should_not include(:before_save)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should not call after_save" do
|
139
|
+
@db.save_document @recorder
|
140
|
+
@recorder.callbacks.should_not include(:after_save)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should not call before_create" do
|
144
|
+
@db.save_document @recorder
|
145
|
+
@recorder.callbacks.should_not include(:before_create)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should not call after_create" do
|
149
|
+
@db.save_document @recorder
|
150
|
+
@recorder.callbacks.should_not include(:after_create)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "update callbacks" do
|
156
|
+
|
157
|
+
before(:each) do
|
158
|
+
@recorder = CallbackRecorder.new :required_property => 1
|
159
|
+
|
160
|
+
couchrest_database = stub 'couchrest_database', :save_doc => {'id' => '1', 'rev' => '2'}, :view => {'rows' => []}, :info => nil
|
161
|
+
@db = CouchTomato::Database.new(couchrest_database)
|
162
|
+
@db.save_document! @recorder
|
163
|
+
|
164
|
+
@recorder.required_property = 2
|
165
|
+
@recorder.callbacks.clear
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "successful update" do
|
169
|
+
|
170
|
+
before(:each) do
|
171
|
+
@db.save_document! @recorder
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should call before_validation" do
|
175
|
+
@recorder.callbacks.should include(:before_validation)
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should call before_validation_on_update" do
|
179
|
+
@recorder.callbacks.should include(:before_validation_on_update)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should call before_validation_on_save" do
|
183
|
+
@recorder.callbacks.should include(:before_validation_on_save)
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should call before_save" do
|
187
|
+
@recorder.callbacks.should include(:before_save)
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should call after_save" do
|
191
|
+
@recorder.callbacks.should include(:after_save)
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should call before_update" do
|
195
|
+
@recorder.callbacks.should include(:before_update)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should call after_update" do
|
199
|
+
@recorder.callbacks.should include(:after_update)
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "failed update" do
|
205
|
+
|
206
|
+
before(:each) do
|
207
|
+
@recorder.required_property = nil
|
208
|
+
@db.save_document @recorder
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should call before_validation" do
|
212
|
+
@recorder.callbacks.should include(:before_validation)
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should call before_validation_on_update" do
|
216
|
+
@recorder.callbacks.should include(:before_validation_on_update)
|
217
|
+
end
|
218
|
+
|
219
|
+
it "should call before_validation_on_save" do
|
220
|
+
@recorder.callbacks.should include(:before_validation_on_save)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should not call before_save" do
|
224
|
+
@recorder.callbacks.should_not include(:before_save)
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should not call after_save" do
|
228
|
+
@recorder.callbacks.should_not include(:after_save)
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should not call before_update" do
|
232
|
+
@recorder.callbacks.should_not include(:before_update)
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should not call after_update" do
|
236
|
+
@recorder.callbacks.should_not include(:after_update)
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
describe "destroy callbacks" do
|
244
|
+
|
245
|
+
before(:each) do
|
246
|
+
@recorder = CallbackRecorder.new :required_property => 1
|
247
|
+
couchrest_database = stub 'couchrest_database', :save_doc => {'id' => '1', 'rev' => '2'}, :delete_doc => nil, :view => {'rows' => []}, :info => nil
|
248
|
+
@db = CouchTomato::Database.new(couchrest_database)
|
249
|
+
@db.save_document! @recorder
|
250
|
+
|
251
|
+
@recorder.callbacks.clear
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should call before_destroy" do
|
255
|
+
@db.destroy_document @recorder
|
256
|
+
@recorder.callbacks.should include(:before_destroy)
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should call after_destroy" do
|
260
|
+
@db.destroy_document @recorder
|
261
|
+
@recorder.callbacks.should include(:after_destroy)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe "lambda callbacks" do
|
266
|
+
it "should run the lambda" do
|
267
|
+
recorder = CallbackRecorder.new
|
268
|
+
recorder.run_callbacks :before_create
|
269
|
+
recorder.lambda_works.should be_true
|
270
|
+
end
|
271
|
+
end
|
data/spec/comment.rb
ADDED
data/spec/create_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "create" do
|
4
|
+
before(:all) do
|
5
|
+
recreate_db
|
6
|
+
end
|
7
|
+
describe "succeeds" do
|
8
|
+
it "should store the class" do
|
9
|
+
@comment = Comment.new :title => 'my_title'
|
10
|
+
CouchTomato.database.save_document! @comment
|
11
|
+
CouchTomato.couchrest_database.get(@comment.id)['ruby_class'].should == 'Comment'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
describe "fails" do
|
15
|
+
it "should not store anything" do
|
16
|
+
@comment = Comment.new
|
17
|
+
CouchTomato.database.save_document @comment
|
18
|
+
CouchTomato.couchrest_database.documents['rows'].should be_empty
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|