lib/dirty_hashy.rb in dirty_hashy-0.1.1 vs lib/dirty_hashy.rb in dirty_hashy-0.1.2

- old
+ new

@@ -3,22 +3,40 @@ require "dirty_attributes" require "method_map" class DirtyHashy < HashWithIndifferentAccess - def self.new(constructor = {}, map_methods = false) - super(constructor).tap do |instance| - if map_methods - instance.extend MethodMap - instance.dirty_map! - end + def initialize(constructor = {}, map_methods = false, restricted_keys = nil) + super constructor + if map_methods + extend MethodMap + dirty_map! end + if restricted_keys + restricted_keys.each{|key| self[key] ||= nil} + @restricted_keys = keys + end end + def replace(other) + clear + merge! other + end + + def clear + keys.each{|key| delete key} + end + + def [](key, mapped = false) + validate_read!(key) if mapped || restricted_keys? + super(key) + end + alias :_regular_writer :regular_writer def regular_writer(key, value) - original_value = changes.key?(key) ? was(key) : self[key] + validate_write!(key) + original_value = changes.key?(key) ? was(key) : fetch(key, nil) if original_value == value changes.delete key else changes[key] = [original_value, value] end @@ -32,24 +50,39 @@ def changes @changes ||= HashWithIndifferentAccess.new end - def changed?(key = nil) + def changed?(key = nil, mapped = false) + validate_read!(key) if !key.nil? && (mapped || restricted_keys?) key.nil? ? !changes.empty? : changes.key?(key) end alias :dirty? :changed? - def change(key) - changes[key] if changed?(key) + def change(key, mapped = false) + changes[key] if changed?(key, mapped) end - def was(key) - change(key).first if changed?(key) + def was(key, mapped = false) + change(key).first if changed?(key, mapped) end def clean_up! changes.clear nil + end + +private + + def restricted_keys? + !(@restricted_keys || []).empty? + end + + def validate_read!(key) + raise IndexError, "Invalid key: \"#{key}\"" unless (keys + changes.keys).include?(key.to_s) + end + + def validate_write!(key) + raise IndexError, "Invalid key: \"#{key}\"" unless @restricted_keys.nil? || @restricted_keys.empty? || @restricted_keys.include?(key.to_s) end end \ No newline at end of file