| 1 | DeepMerge Overview |
|---|
| 2 | ================== |
|---|
| 3 | |
|---|
| 4 | Deep Merge is a simple set of utility functions for Hash. It permits |
|---|
| 5 | you to merge elements inside a hash together recursively. The manner |
|---|
| 6 | by which it does this is somewhat arbitrary (since there is no defining |
|---|
| 7 | standard for this) but it should end up being pretty intuitive and do what |
|---|
| 8 | you expect. |
|---|
| 9 | |
|---|
| 10 | You can learn a lot more about this by reading the test file. It's pretty |
|---|
| 11 | well documented and has many examples of various merges from very simple |
|---|
| 12 | to pretty complex. |
|---|
| 13 | |
|---|
| 14 | The primary need that caused me to write this library is the merging of elements |
|---|
| 15 | coming from HTTP parameters and related stored parameters in session. This lets |
|---|
| 16 | a user build up a set of parameters over time, modifying individual items. |
|---|
| 17 | |
|---|
| 18 | Deep Merge Core Documentation |
|---|
| 19 | ============================= |
|---|
| 20 | There are three key methods that are added to Hash when you require deep_merge: |
|---|
| 21 | |
|---|
| 22 | deep_merge!(new_hash[, opts]) -- merges and new_hash wins unmergeable situations |
|---|
| 23 | deep_merge(new_hash[, opts]) -- merges and "self" hash wins unmergeable situations |
|---|
| 24 | ko_deep_merge!(new_hash[, opts]) -- same as deep_merge! but "--" provides "knockout" functions |
|---|
| 25 | |
|---|
| 26 | deep_merge! method permits merging of arbitrary child elements. The two top level |
|---|
| 27 | elements must be hashes. These hashes can contain unlimited (to stack limit) levels |
|---|
| 28 | of child elements. These child elements to not have to be of the same types. |
|---|
| 29 | Where child elements are of the same type, deep_merge will attempt to merge them together. |
|---|
| 30 | Where child elements are not of the same type, deep_merge will skip or optionally overwrite |
|---|
| 31 | the destination element with the contents of the source element at that level. |
|---|
| 32 | So if you have two hashes like this: |
|---|
| 33 | source = {:x => [1,2,3], :y => 2} |
|---|
| 34 | dest = {:x => [4,5,'6'], :y => [7,8,9]} |
|---|
| 35 | dest.deep_merge!(source) |
|---|
| 36 | Results: {:x => [1,2,3,4,5,'6'], :y => 2} |
|---|
| 37 | By default, "deep_merge!" will overwrite any unmergeables and merge everything else. |
|---|
| 38 | To avoid this, use "deep_merge" (no bang/exclamation mark) |
|---|
| 39 | |
|---|
| 40 | Options: |
|---|
| 41 | Options are specified in the last parameter passed, which should be in hash format: |
|---|
| 42 | hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'}) |
|---|
| 43 | :preserve_unmergeables DEFAULT: false |
|---|
| 44 | Set to true to skip any unmergeable elements from source |
|---|
| 45 | :knockout_prefix DEFAULT: nil |
|---|
| 46 | Set to string value to signify prefix which deletes elements from existing element |
|---|
| 47 | :sort_merged_arrays DEFAULT: false |
|---|
| 48 | Set to true to sort all arrays that are merged together |
|---|
| 49 | :unpack_arrays DEFAULT: nil |
|---|
| 50 | Set to string value to run "Array::join" then "String::split" against all arrays |
|---|
| 51 | :merge_debug DEFAULT: false |
|---|
| 52 | Set to true to get console output of merge process for debugging |
|---|
| 53 | |
|---|
| 54 | Selected Options Details: |
|---|
| 55 | :knockout_prefix => The purpose of this is to provide a way to remove elements |
|---|
| 56 | from existing Hash by specifying them in a special way in incoming hash |
|---|
| 57 | source = {:x => ['--1', '2']} |
|---|
| 58 | dest = {:x => ['1', '3']} |
|---|
| 59 | dest.ko_deep_merge!(source) |
|---|
| 60 | Results: {:x => ['2','3']} |
|---|
| 61 | Additionally, if the knockout_prefix is passed alone as a string, it will cause |
|---|
| 62 | the entire element to be removed: |
|---|
| 63 | source = {:x => '--'} |
|---|
| 64 | dest = {:x => [1,2,3]} |
|---|
| 65 | dest.ko_deep_merge!(source) |
|---|
| 66 | Results: {:x => ""} |
|---|
| 67 | :unpack_arrays => The purpose of this is to permit compound elements to be passed |
|---|
| 68 | in as strings and to be converted into discrete array elements |
|---|
| 69 | irsource = {:x => ['1,2,3', '4']} |
|---|
| 70 | dest = {:x => ['5','6','7,8']} |
|---|
| 71 | dest.deep_merge!(source, {:unpack_arrays => ','}) |
|---|
| 72 | Results: {:x => ['1','2','3','4','5','6','7','8'} |
|---|
| 73 | Why: If receiving data from an HTML form, this makes it easy for a checkbox |
|---|
| 74 | to pass multiple values from within a single HTML element |
|---|
| 75 | |
|---|
| 76 | There are many tests for this library - and you can learn more about the features |
|---|
| 77 | and usages of deep_merge! by just browsing the test examples |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | Simple Example Code |
|---|
| 81 | =================== |
|---|
| 82 | |
|---|
| 83 | require 'deep_merge' |
|---|
| 84 | x = {:x => [3,4,5]} |
|---|
| 85 | y = {:x => [1,2,3]} |
|---|
| 86 | y.deep_merge!(x) |
|---|
| 87 | # results: y = {:x => [1,2,3,4,5]} |
|---|
| 88 | |
|---|
| 89 | Availablility |
|---|
| 90 | ============= |
|---|
| 91 | SVN Repo here: http://trac.misuse.org/science/wiki/DeepMerge |
|---|
| 92 | Contact author: http://www.misuse.org/science |
|---|
| 93 | |
|---|
| 94 | Copyright (c) 2008 Steve Midgley, released under the MIT license |
|---|