merb_app_config 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -17,4 +17,7 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
17
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+
23
+ Deep Merge (deep_merge.rb) code Copyright (c) 2008 Steve Midgley, released under the MIT license
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'merb-core'
5
5
  require 'merb-core/tasks/merb'
6
6
 
7
7
  GEM_NAME = "merb_app_config"
8
- GEM_VERSION = "1.0.5"
8
+ GEM_VERSION = "1.0.6"
9
9
  AUTHOR = "Jacques Crocker"
10
10
  EMAIL = "merbjedi@gmail.com"
11
11
  HOMEPAGE = "http://www.merbjedi.com/"
@@ -1,6 +1,7 @@
1
1
  require 'ostruct'
2
2
  require 'yaml'
3
3
  require 'erb'
4
+ require 'deep_merge'
4
5
 
5
6
  module ApplicationConfig
6
7
  # == Summary
@@ -24,7 +25,7 @@ module ApplicationConfig
24
25
  conf = {}
25
26
  ConfigBuilder.load_paths.to_a.each do |path|
26
27
  file_conf = YAML.load(ERB.new(IO.read(path)).result) if path and File.exists?(path)
27
- conf.merge!(file_conf) if file_conf
28
+ DeepMerge.deep_merge!(file_conf, conf) if file_conf
28
29
  end
29
30
 
30
31
  # expand the javascripts config to handle *.* paths
@@ -0,0 +1,181 @@
1
+ module DeepMerge
2
+
3
+ class InvalidParameter < StandardError; end
4
+
5
+ DEFAULT_FIELD_KNOCKOUT_PREFIX = '--'
6
+
7
+ # Deep Merge core documentation.
8
+ # deep_merge! method permits merging of arbitrary child elements. The two top level
9
+ # elements must be hashes. These hashes can contain unlimited (to stack limit) levels
10
+ # of child elements. These child elements to not have to be of the same types.
11
+ # Where child elements are of the same type, deep_merge will attempt to merge them together.
12
+ # Where child elements are not of the same type, deep_merge will skip or optionally overwrite
13
+ # the destination element with the contents of the source element at that level.
14
+ # So if you have two hashes like this:
15
+ # source = {:x => [1,2,3], :y => 2}
16
+ # dest = {:x => [4,5,'6'], :y => [7,8,9]}
17
+ # dest.deep_merge!(source)
18
+ # Results: {:x => [1,2,3,4,5,'6'], :y => 2}
19
+ # By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
20
+ # To avoid this, use "deep_merge" (no bang/exclamation mark)
21
+ #
22
+ # Options:
23
+ # Options are specified in the last parameter passed, which should be in hash format:
24
+ # hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'})
25
+ # :preserve_unmergeables DEFAULT: false
26
+ # Set to true to skip any unmergeable elements from source
27
+ # :knockout_prefix DEFAULT: nil
28
+ # Set to string value to signify prefix which deletes elements from existing element
29
+ # :sort_merged_arrays DEFAULT: false
30
+ # Set to true to sort all arrays that are merged together
31
+ # :unpack_arrays DEFAULT: nil
32
+ # Set to string value to run "Array::join" then "String::split" against all arrays
33
+ # :merge_debug DEFAULT: false
34
+ # Set to true to get console output of merge process for debugging
35
+ #
36
+ # Selected Options Details:
37
+ # :knockout_prefix => The purpose of this is to provide a way to remove elements
38
+ # from existing Hash by specifying them in a special way in incoming hash
39
+ # source = {:x => ['--1', '2']}
40
+ # dest = {:x => ['1', '3']}
41
+ # dest.ko_deep_merge!(source)
42
+ # Results: {:x => ['2','3']}
43
+ # Additionally, if the knockout_prefix is passed alone as a string, it will cause
44
+ # the entire element to be removed:
45
+ # source = {:x => '--'}
46
+ # dest = {:x => [1,2,3]}
47
+ # dest.ko_deep_merge!(source)
48
+ # Results: {:x => ""}
49
+ # :unpack_arrays => The purpose of this is to permit compound elements to be passed
50
+ # in as strings and to be converted into discrete array elements
51
+ # irsource = {:x => ['1,2,3', '4']}
52
+ # dest = {:x => ['5','6','7,8']}
53
+ # dest.deep_merge!(source, {:unpack_arrays => ','})
54
+ # Results: {:x => ['1','2','3','4','5','6','7','8'}
55
+ # Why: If receiving data from an HTML form, this makes it easy for a checkbox
56
+ # to pass multiple values from within a single HTML element
57
+ #
58
+ # There are many tests for this library - and you can learn more about the features
59
+ # and usages of deep_merge! by just browsing the test examples
60
+ def DeepMerge.deep_merge!(source, dest, options = {})
61
+ # turn on this line for stdout debugging text
62
+ merge_debug = options[:merge_debug] || false
63
+ overwrite_unmergeable = !options[:preserve_unmergeables]
64
+ knockout_prefix = options[:knockout_prefix] || nil
65
+ if knockout_prefix == "" : raise InvalidParameter, "knockout_prefix cannot be an empty string in deep_merge!"; end
66
+ if knockout_prefix && !overwrite_unmergeable : raise InvalidParameter, "overwrite_unmergeable must be true if knockout_prefix is specified in deep_merge!"; end
67
+ # if present: we will split and join arrays on this char before merging
68
+ array_split_char = options[:unpack_arrays] || false
69
+ # request that we sort together any arrays when they are merged
70
+ sort_merged_arrays = options[:sort_merged_arrays] || false
71
+ di = options[:debug_indent] || ''
72
+ # do nothing if source is nil
73
+ if !source || (source.respond_to?(:blank?) && source.blank?) : return dest; end
74
+ # if dest doesn't exist, then simply copy source to it
75
+ if !(dest) && overwrite_unmergeable : dest = source; return dest; end
76
+
77
+ puts "#{di}Source class: #{source.class.inspect} :: Dest class: #{dest.class.inspect}" if merge_debug
78
+ if source.kind_of?(Hash)
79
+ puts "#{di}Hashes: #{source.inspect} :: #{dest.inspect}" if merge_debug
80
+ source.each do |src_key, src_value|
81
+ if dest.kind_of?(Hash)
82
+ puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug
83
+ if dest[src_key]
84
+ puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug
85
+ dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(:debug_indent => di + ' '))
86
+ else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!)
87
+ puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug
88
+ # note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
89
+ begin
90
+ src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty)
91
+ rescue TypeError
92
+ src_dup = src_value
93
+ end
94
+ dest[src_key] = deep_merge!(src_value, src_dup, options.merge(:debug_indent => di + ' '))
95
+ end
96
+ else # dest isn't a hash, so we overwrite it completely (if permitted)
97
+ if overwrite_unmergeable
98
+ puts "#{di} overwriting dest: #{src_key.inspect} => #{src_value.inspect} -over-> #{dest.inspect}" if merge_debug
99
+ dest = overwrite_unmergeables(source, dest, options)
100
+ end
101
+ end
102
+ end
103
+ elsif source.kind_of?(Array)
104
+ puts "#{di}Arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
105
+ # if we are instructed, join/split any source arrays before processing
106
+ if array_split_char
107
+ puts "#{di} split/join on source: #{source.inspect}" if merge_debug
108
+ source = source.join(array_split_char).split(array_split_char)
109
+ if dest.kind_of?(Array) : dest = dest.join(array_split_char).split(array_split_char); end
110
+ end
111
+ # if there's a naked knockout_prefix in source, that means we are to truncate dest
112
+ if source.index(knockout_prefix) : dest = clear_or_nil(dest); source.delete(knockout_prefix); end
113
+ if dest.kind_of?(Array)
114
+ if knockout_prefix
115
+ print "#{di} knocking out: " if merge_debug
116
+ # remove knockout prefix items from both source and dest
117
+ source.delete_if do |ko_item|
118
+ retval = false
119
+ item = ko_item.respond_to?(:gsub) ? ko_item.gsub(%r{^#{knockout_prefix}}, "") : ko_item
120
+ if item != ko_item
121
+ print "#{ko_item} - " if merge_debug
122
+ dest.delete(item)
123
+ dest.delete(ko_item)
124
+ retval = true
125
+ end
126
+ retval
127
+ end
128
+ puts if merge_debug
129
+ end
130
+ puts "#{di} merging arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
131
+ dest = dest | source
132
+ if sort_merged_arrays : dest.sort!; end
133
+ elsif overwrite_unmergeable
134
+ puts "#{di} overwriting dest: #{source.inspect} -over-> #{dest.inspect}" if merge_debug
135
+ dest = overwrite_unmergeables(source, dest, options)
136
+ end
137
+ else # src_hash is not an array or hash, so we'll have to overwrite dest
138
+ puts "#{di}Others: #{source.inspect} :: #{dest.inspect}" if merge_debug
139
+ dest = overwrite_unmergeables(source, dest, options)
140
+ end
141
+ puts "#{di}Returning #{dest.inspect}" if merge_debug
142
+ dest
143
+ end # deep_merge!
144
+
145
+ # allows deep_merge! to uniformly handle overwriting of unmergeable entities
146
+ def DeepMerge::overwrite_unmergeables(source, dest, options)
147
+ merge_debug = options[:merge_debug] || false
148
+ overwrite_unmergeable = !options[:preserve_unmergeables]
149
+ knockout_prefix = options[:knockout_prefix] || false
150
+ di = options[:debug_indent] || ''
151
+ if knockout_prefix && overwrite_unmergeable
152
+ if source.kind_of?(String) # remove knockout string from source before overwriting dest
153
+ src_tmp = source.gsub(%r{^#{knockout_prefix}},"")
154
+ elsif source.kind_of?(Array) # remove all knockout elements before overwriting dest
155
+ src_tmp = source.delete_if {|ko_item| ko_item.kind_of?(String) && ko_item.match(%r{^#{knockout_prefix}}) }
156
+ else
157
+ src_tmp = source
158
+ end
159
+ if src_tmp == source # if we didn't find a knockout_prefix then we just overwrite dest
160
+ puts "#{di}#{src_tmp.inspect} -over-> #{dest.inspect}" if merge_debug
161
+ dest = src_tmp
162
+ else # if we do find a knockout_prefix, then we just delete dest
163
+ puts "#{di}\"\" -over-> #{dest.inspect}" if merge_debug
164
+ dest = ""
165
+ end
166
+ elsif overwrite_unmergeable
167
+ dest = source
168
+ end
169
+ dest
170
+ end
171
+
172
+ def DeepMerge::clear_or_nil(obj)
173
+ if obj.respond_to?(:clear)
174
+ obj.clear
175
+ else
176
+ obj = nil
177
+ end
178
+ obj
179
+ end
180
+
181
+ end # module DeepMerge
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: merb_app_config
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacques Crocker
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-23 00:00:00 -07:00
12
+ date: 2009-07-30 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -36,6 +36,7 @@ files:
36
36
  - README
37
37
  - Rakefile
38
38
  - lib/application_config/config_builder.rb
39
+ - lib/application_config/deep_merge.rb
39
40
  - lib/application_config/view_helpers.rb
40
41
  - lib/merb_app_config.rb
41
42
  - lib/merbtasks.rb
@@ -63,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
64
  requirements: []
64
65
 
65
66
  rubyforge_project: merb
66
- rubygems_version: 1.3.2
67
+ rubygems_version: 1.3.4
67
68
  signing_key:
68
69
  specification_version: 3
69
70
  summary: Merb plugin that provides easy to use Application Configurations via YAML