Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require 'hash/dirty'
- # DirtyHash behaves just like Hash, but keeps track of changes applied to it.
- #
- # @example
- # dh = DirtyHash.with :x => 1
- # dh.clean? # => true
- # dh.update :y => 2, :z => 4
- # dh.changed # => {:y => [:added, 2], :z => [:added, nil, 4]}
- # dh[:z] = 3
- # dh.changed # => {:y => [:added, 2], :z => [:replaced, 4, 3]}
- # dh.reject! { |key, value| value > 2 }
- # dh.changed # => {:y => [:added, 2], :z => [:deleted, 3, nil]}
- # dh.dirty? # => true
- # dh.clean!
- # dh.changed # => {}
- #
- # @note
- # The behaviour of the following methods remains to be defined: ==, eql?, hash
- class DirtyHash < Hash
- include Hash::Dirty
- # Create a DirtyHash with prepopulated data.
- # The returned DirtyHash is clean.
- # If a second argument is provided, the first argument is used as default value.
- # A block is given, it is used as default_proc.
- #
- # @overload with(:prefilled => 'data')
- # @param [Hash, DirtyHash, #to_hash] prefilled_data
- # The data to fill the dirty hash with
- #
- # @overload with(:default_value, :prefilled => 'data')
- # @param [Object] default
- # The default value, it is returned instead of nil when trying to access a yet undefined key
- # @param [Hash, DirtyHash, #to_hash] prefilled_data
- # The data to fill the dirty hash with
- #
- # @overload with(:prefilled => 'data', &default_proc)
- # @param [Hash, DirtyHash, #to_hash] prefilled_data
- # The data to fill the dirty hash with
- # @yield [key, dirty_hash]
- # The default proc will be called with the hash object and the key, and should return the
- # default value. It is the block's responsibility to store the value in the hash if required.
- #
- # @example
- # dh1 = DirtyHash#with :x => "hello", :y => "world" # => DirtyHash{:x=>"hello",:y=>"world"}
- # dh2 = DirtyHash#with "foo", :x => "hello" # => DirtyHash{:x=>"hello"}
- # dh2[:undefined] # => "foo"
- # dh3 = DirtyHash#with :x => 1 do |dh,key| dh[key] = "bar" end
- # dh3[:becoming_defined] # => "bar"
- # dh3 # => DirtyHash{:x=>1,:becoming_defined=>"bar"}
- #
- # @see DirtyHash::new
- def self.with(*args, &block)
- raise ArgumentError, "wrong number of arguments (0 for 1)" if args.empty?
- prefilled_data = args.pop
- dirty_hash = new(*args, &block)
- unless prefilled_data.is_a?(Hash) then
- if prefilled_data.respond_to?(:to_hash) then
- prefilled_data = prefilled_data.to_hash
- else
- raise ArgumentError, "prefilled_data must respond to to_hash"
- end
- end
- dirty_hash.update(prefilled_data)
- dirty_hash.clean_changes!
- dirty_hash
- end
- def self.[](*)
- dirty_hash = super
- dirty_hash.send :initialize_dirty
- dirty_hash.clean_changes!
- dirty_hash
- end
- end
Add Comment
Please, Sign In to add comment