Skip to content
Browse files

make SimplyStored compatible with latest CouchPotato - ActiveModel Ca…

…llbacks and Dirty are fun... NOT!
  • Loading branch information...
1 parent 9c27a91 commit c9ed8efb173541b7261621e0d666fe471e98a3b8 @jweiss jweiss committed
View
6 Gemfile
@@ -2,9 +2,9 @@ gem "uuidtools"
gem "mattmatt-validatable", '1.8.4'
gem 'rest-client', '1.6.1', :require => 'restclient'
gem 'couchrest', '1.0.1'
-gem 'couch_potato', '0.2.31.2'
+gem 'couch_potato', '0.4.0'
gem 'shoulda'
gem 'shoulda-addons'
gem 'mocha'
-gem 'activesupport', '2.3.11', :require => 'active_support'
-gem 'right_aws'
+gem 'activesupport', '3.0.0', :require => 'active_support'
+gem 'right_aws'
View
22 lib/simply_stored.rb
@@ -1,12 +1,14 @@
-$:<<(File.expand_path(File.dirname(__FILE__) + "/lib"))
-require File.expand_path(File.dirname(__FILE__) + '/simply_stored/instance_methods')
-require File.expand_path(File.dirname(__FILE__) + '/simply_stored/storage')
-require File.expand_path(File.dirname(__FILE__) + '/simply_stored/class_methods_base')
+unless defined?(SimplyStored)
+ $:<<(File.expand_path(File.dirname(__FILE__) + "/lib"))
+ require File.expand_path(File.dirname(__FILE__) + '/simply_stored/instance_methods')
+ require File.expand_path(File.dirname(__FILE__) + '/simply_stored/storage')
+ require File.expand_path(File.dirname(__FILE__) + '/simply_stored/class_methods_base')
-module SimplyStored
- VERSION = '0.5.3'
- class Error < RuntimeError; end
- class RecordNotFound < RuntimeError; end
-end
+ module SimplyStored
+ VERSION = '0.5.3'
+ class Error < RuntimeError; end
+ class RecordNotFound < RuntimeError; end
+ end
-require File.expand_path(File.dirname(__FILE__) + '/simply_stored/couch')
+ require File.expand_path(File.dirname(__FILE__) + '/simply_stored/couch')
+end
View
32 lib/simply_stored/couch.rb
@@ -19,6 +19,8 @@
require 'simply_stored/couch/ext/couch_potato'
require 'simply_stored/couch/views'
+CouchPotato::Config.validation_framework = :validatable
+
module SimplyStored
module Couch
def self.included(clazz)
@@ -30,8 +32,6 @@ def self.included(clazz)
clazz.instance_eval do
attr_accessor :_accessible_attributes, :_protected_attributes
- alias :simpledb_array :simpledb_string
- alias :simpledb_integer :simpledb_string
view :all_documents, :key => :created_at
end
@@ -84,34 +84,6 @@ def auto_conflict_resolution_on_save=(val)
@auto_conflict_resolution_on_save = val
end
- def simpledb_string(*names)
- names.each do |name|
- property name
- end
- end
-
- def simpledb_timestamp(*names)
- names.each do |name|
- property name, :type => Time
- end
- end
-
- def require_attributes(*names)
- names.each do |name|
- validates_presence_of name
- end
- end
-
- def require_inclusion_of(name, valid_set, options = {})
- options.update(:in => valid_set)
- validates_inclusion_of(name, options)
- end
-
- def require_format_of(attr, valid_regex, options = {})
- options.update(:with => valid_regex)
- validates_format_of(attr, options)
- end
-
def method_missing(name, *args)
if name.to_s =~ /^find_by/
_define_find_by(name, *args)
View
15 lib/simply_stored/couch/belongs_to.rb
@@ -56,7 +56,6 @@ def initialize(owner_clazz, name, options = {})
@options.assert_valid_keys(:class_name)
owner_clazz.class_eval do
- attr_reader "#{name}_id"
attr_accessor "#{name}_id_was"
property "#{name}_id"
@@ -74,17 +73,17 @@ def initialize(owner_clazz, name, options = {})
klass = self.class.get_class_from_name(self.class._find_property(name).options[:class_name])
raise ArgumentError, "expected #{klass} got #{value.class}" unless value.nil? || value.is_a?(klass)
+ new_foreign_id = value.nil? ? nil : value.id
+
+ send("#{name}_id_will_change!") if send("#{name}_id_was") != new_foreign_id
+ send("#{name}_id=", new_foreign_id)
instance_variable_set("@#{name}", value)
- if value.nil?
- instance_variable_set("@#{name}_id", nil)
- else
- instance_variable_set("@#{name}_id", value.id)
- end
end
- define_method "#{name}_id=" do |id|
+ define_method "#{name}_id=" do |new_foreign_id|
remove_instance_variable("@#{name}") if instance_variable_defined?("@#{name}")
- instance_variable_set("@#{name}_id", id)
+ send("#{name}_id_will_change!") if send("#{name}_id_was") != new_foreign_id
+ instance_variable_set("@#{name}_id", new_foreign_id)
end
define_method "#{name}_changed?" do
View
26 lib/simply_stored/couch/ext/couch_potato.rb
@@ -4,6 +4,12 @@ module DirtyAttributes
private
def reset_dirty_attributes
+ # active mode reset
+ @previously_changed = changes
+ @changed_attributes.clear
+ @forced_dirty = nil
+
+ # belongs_to properties reset
self.class.properties.each do |property|
if !property.respond_to?(:supports_dirty?) || property.supports_dirty?
property.respond_to?(:reset_dirty_attribute) ? property.reset_dirty_attribute(self) :
@@ -13,4 +19,24 @@ def reset_dirty_attributes
end
end
end
+end
+
+module CouchPotato
+ class Database
+
+ # the original implementation does not delete if callbacks are skipped
+ def destroy_document(document, run_callbacks = true)
+ if run_callbacks
+ document.run_callbacks :destroy do
+ document._deleted = true
+ database.delete_doc document.to_hash
+ end
+ else
+ document._deleted = true
+ database.delete_doc document.to_hash
+ end
+ document._id = nil
+ document._rev = nil
+ end
+ end
end
View
2 lib/simply_stored/couch/has_many.rb
@@ -81,7 +81,7 @@ def define_has_many_setter_remove(name, options)
elsif options[:dependent] == :ignore
# skip
else # nullify
- value.send("#{self.class.foreign_key}=", nil)
+ value.send("#{self.class.foreign_key}=", nil)
value.save(false)
end
View
22 lib/simply_stored/instance_methods.rb
@@ -29,12 +29,18 @@ def save!
def destroy(override_soft_delete=false)
check_and_destroy_dependents
if self.class.soft_deleting_enabled? && !override_soft_delete
+ # soft-delete
_mark_as_deleted
else
- self.skip_callbacks = true if self.class.soft_deleting_enabled? && deleted?
- CouchPotato.database.destroy_document(self)
+ if self.class.soft_deleting_enabled? && deleted?
+ # really deleting a previously soft-deleted object - skipping callbacks
+ CouchPotato.database.destroy_document(self, false)
+ else # deleting a normal object or a soft-deletable object that was not soft-deleted before
+ CouchPotato.database.destroy_document(self, true)
+ end
freeze
end
+ self
end
alias :delete :destroy
@@ -65,8 +71,8 @@ def deleted?
false
end
end
-
- protected
+
+ protected
def retry_on_conflict(max_retries = 2, &blk)
retry_count = 0
@@ -255,10 +261,10 @@ def count_associated_via_join_view(from, to, options = {})
end
def _mark_as_deleted
- run_callbacks(:before_destroy)
- send("#{self.class.soft_delete_attribute}=", Time.now)
- save(false)
- run_callbacks(:after_destroy)
+ _run_destroy_callbacks do
+ send("#{self.class.soft_delete_attribute}=", Time.now)
+ save(false)
+ end
end
end
View
13 test/belongs_to_test.rb
@@ -30,7 +30,18 @@ class ::DoubleBelongsToUser
post = Post.find(post.id)
assert_equal user.id, post.user_id
end
+
+ should "create a property for the foreign key attribute" do
+ assert Post.properties.any?{|p| p.is_a?(CouchPotato::Persistence::SimpleProperty) && p.name == 'user_id'}
+ end
+ should "notice a change to the foreign key attribute in dirty checks" do
+ user = User.create!(:title => 'Prof')
+ post = Post.create!
+ post.user = user
+ assert post.user_id_changed?
+ end
+
should "set also the foreign key id to nil if setting the referencing object to nil" do
user = User.create(:title => "Mr.")
post = Post.create(:user => user)
@@ -63,7 +74,7 @@ class ::DoubleBelongsToUser
post.save
post = Post.find(post.id)
- assert_equal user2, post.user
+ assert_equal user2.id, post.user.id
end
should "check the class and raise an error if not matching in belongs_to setter" do
View
2 test/instance_lifecycle_test.rb
@@ -205,7 +205,7 @@ class InstanceLifecycleTest < Test::Unit::TestCase
user2 = User.find(user.id)
user2.update_attributes(:title => "Mrs.", :name => "Hostess Masteress")
user.reload
- assert !user.dirty?
+ assert !user.dirty?, user.changes.inspect
end
should "ensure that association caches for has_many are cleared" do
View
12 test/soft_deletable_test.rb
@@ -65,9 +65,15 @@ class SoftDeletableTest < Test::Unit::TestCase
CouchPotato.database.expects(:destroy_document).never
@hemorrhoid.destroy
end
+
+ should "really delete with callbacks" do
+ CouchPotato.database.expects(:destroy_document).with(@hemorrhoid, true)
+ @hemorrhoid.destroy!
+ end
- should "really delete if asked to" do
- CouchPotato.database.expects(:destroy_document).with(@hemorrhoid)
+ should "really delete without callbacks if the object was soft-deleted before" do
+ CouchPotato.database.expects(:destroy_document).with(@hemorrhoid, false)
+ @hemorrhoid.destroy
@hemorrhoid.destroy!
end
@@ -110,7 +116,7 @@ def @hemorrhoid.deleted?
end
end
- should "not fire the callbacks on the real destroy if the object is not deleted" do
+ should "fire the callbacks on the real destroy if the object is not deleted" do
@hemorrhoid = Hemorrhoid.create
$before = nil
$after = nil

0 comments on commit c9ed8ef

Please sign in to comment.
Something went wrong with that request. Please try again.