implemented some missing dirty functionality for casted_array and casted_hash. improved dirty spec test

This commit is contained in:
Andrew Williams 2011-03-03 23:22:19 +10:30
parent dcf43e3641
commit 2a9305ebd3
8 changed files with 284 additions and 35 deletions

View file

@ -15,36 +15,41 @@ module CouchRest::Model
end
def << obj
couchrest_parent_will_change!
couchrest_parent_will_change! if use_dirty?
super(instantiate_and_cast(obj))
end
def push(obj)
couchrest_parent_will_change!
couchrest_parent_will_change! if use_dirty?
super(instantiate_and_cast(obj))
end
def pop
couchrest_parent_will_change!
couchrest_parent_will_change! if use_dirty? && self.length > 0
super
end
def shift
couchrest_parent_will_change!
couchrest_parent_will_change! if use_dirty? && self.length > 0
super
end
def unshift(obj)
couchrest_parent_will_change!
super(obj)
couchrest_parent_will_change! if use_dirty?
super(instantiate_and_cast(obj))
end
def []= index, obj
value = instantiate_and_cast(obj)
couchrest_parent_will_change! if value != self[index]
couchrest_parent_will_change! if use_dirty? && value != self[index]
super(index, value)
end
def clear
couchrest_parent_will_change! if use_dirty? && self.length > 0
super
end
protected
def instantiate_and_cast(obj)

View file

@ -6,16 +6,70 @@ module CouchRest::Model
include CouchRest::Model::Dirty
attr_accessor :casted_by
def []= index, obj
return super(index, obj) unless use_dirty?
couchrest_parent_will_change! if obj != self[index]
super(index, obj)
end
# needed for dirty
def attributes
self
end
def []= key, obj
couchrest_attribute_will_change!(key) if use_dirty? && obj != self[key]
super(key, obj)
end
def delete(key)
couchrest_attribute_will_change!(key) if use_dirty? && include?(key)
super(key)
end
def merge!(other_hash)
if use_dirty? && other_hash && other_hash.kind_of?(Hash)
other_hash.keys.each do |key|
if self[key] != other_hash[key] || !include?(key)
couchrest_attribute_will_change!(key)
end
end
end
super(other_hash)
end
def replace(other_hash)
if use_dirty? && other_hash && other_hash.kind_of?(Hash)
# new keys and changed keys
other_hash.keys.each do |key|
if self[key] != other_hash[key] || !include?(key)
couchrest_attribute_will_change!(key)
end
end
# old keys
old_keys = self.keys.reject { |key| other_hash.include?(key) }
old_keys.each { |key| couchrest_attribute_will_change!(key) }
end
super(other_hash)
end
def clear
self.keys.each { |key| couchrest_attribute_will_change!(key) } if use_dirty?
super
end
def delete_if
if use_dirty? && block_given?
self.keys.each do |key|
couchrest_attribute_will_change!(key) if yield key, self[key]
end
end
super
end
def keep_if
if use_dirty? && block_given?
self.keys.each do |key|
couchrest_attribute_will_change!(key) if !yield key, self[key]
end
end
super
end
end
end

View file

@ -13,11 +13,6 @@ module CouchRest
include CouchRest::Model::CastedBy # needed for base_doc
include ActiveModel::Dirty
def use_dirty?
bdoc = base_doc
bdoc && !bdoc.disable_dirty && bdoc.use_dirty
end
included do
# internal dirty setting - overrides global setting.
# this is used to temporarily disable dirty tracking when setting
@ -25,6 +20,11 @@ module CouchRest
self.send(:attr_accessor, :disable_dirty)
end
def use_dirty?
bdoc = base_doc
bdoc && !bdoc.disable_dirty && bdoc.use_dirty
end
def couchrest_attribute_will_change!(attr)
return if attr.nil? || !use_dirty?
attribute_will_change!(attr)

View file

@ -201,7 +201,7 @@ module CouchRest
end
type = [type] # inject as an array
end
property = Property.new(name, type, options)
property = Property.new(name, type, options.merge(:use_dirty => use_dirty))
create_property_getter(property)
create_property_setter(property) unless property.read_only == true
if property.type_class.respond_to?(:validates_casted_model)

View file

@ -4,7 +4,7 @@ module CouchRest::Model
include ::CouchRest::Model::Typecast
attr_reader :name, :type, :type_class, :read_only, :alias, :default, :casted, :init_method, :options
attr_reader :name, :type, :type_class, :read_only, :alias, :default, :casted, :init_method, :use_dirty, :options
# Attribute to define.
# All Properties are assumed casted unless the type is nil.
@ -38,7 +38,7 @@ module CouchRest::Model
end
arr = value.collect { |data| cast_value(parent, data) }
# allow casted_by calls to be passed up chain by wrapping in CastedArray
value = type_class != String ? CastedArray.new(arr, self) : arr
value = (use_dirty || type_class != String) ? CastedArray.new(arr, self) : arr
value.casted_by = parent if value.respond_to?(:casted_by)
elsif (type == Object || type == Hash) && (value.class == Hash)
# allow casted_by calls to be passed up chain by wrapping in CastedHash
@ -94,6 +94,7 @@ module CouchRest::Model
@alias = options.delete(:alias) if options[:alias]
@default = options.delete(:default) unless options[:default].nil?
@init_method = options[:init_method] ? options.delete(:init_method) : 'new'
@use_dirty = options.delete(:use_dirty)
@options = options
end