ccls-common_lib 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.rdoc +116 -0
- data/lib/ccls-common_lib.rb +1 -0
- data/lib/common_lib.rb +37 -0
- data/lib/common_lib/action_controller_extension.rb +8 -0
- data/lib/common_lib/action_controller_extension/accessible_via_protocol.rb +405 -0
- data/lib/common_lib/action_controller_extension/accessible_via_user.rb +605 -0
- data/lib/common_lib/action_controller_extension/routing.rb +20 -0
- data/lib/common_lib/action_controller_extension/test_case.rb +22 -0
- data/lib/common_lib/action_view_extension.rb +3 -0
- data/lib/common_lib/action_view_extension/base.rb +310 -0
- data/lib/common_lib/action_view_extension/form_builder.rb +197 -0
- data/lib/common_lib/active_model.rb +4 -0
- data/lib/common_lib/active_model/errors.rb +16 -0
- data/lib/common_lib/active_model/validations/absence.rb +78 -0
- data/lib/common_lib/active_model/validations/complete_date.rb +138 -0
- data/lib/common_lib/active_model/validations/past_date.rb +121 -0
- data/lib/common_lib/active_record.rb +1 -0
- data/lib/common_lib/active_record/base.rb +129 -0
- data/lib/common_lib/active_support_extension.rb +12 -0
- data/lib/common_lib/active_support_extension/assertions.rb +108 -0
- data/lib/common_lib/active_support_extension/associations.rb +154 -0
- data/lib/common_lib/active_support_extension/attributes.rb +296 -0
- data/lib/common_lib/active_support_extension/pending.rb +115 -0
- data/lib/common_lib/active_support_extension/test_case.rb +203 -0
- data/lib/common_lib/railtie.rb +48 -0
- data/lib/common_lib/ruby.rb +8 -0
- data/lib/common_lib/ruby/array.rb +128 -0
- data/lib/common_lib/ruby/fixnum.rb +5 -0
- data/lib/common_lib/ruby/hash.rb +51 -0
- data/lib/common_lib/ruby/integer.rb +11 -0
- data/lib/common_lib/ruby/nil_class.rb +13 -0
- data/lib/common_lib/ruby/numeric.rb +0 -0
- data/lib/common_lib/ruby/object.rb +53 -0
- data/lib/common_lib/ruby/string.rb +20 -0
- data/lib/common_lib/translation_table.rb +129 -0
- data/lib/tasks/common_lib.rake +10 -0
- data/lib/tasks/csv.rake +0 -0
- data/lib/tasks/database.rake +229 -0
- data/lib/tasks/rcov.rake +52 -0
- data/vendor/assets/javascripts/common_lib.js +77 -0
- data/vendor/assets/stylesheets/common_lib.css +71 -0
- metadata +84 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
module CommonLib::Hash # :nodoc:
|
2
|
+
|
3
|
+
# delete all keys matching the given regex
|
4
|
+
# and return the new hash
|
5
|
+
def delete_keys_matching!(regex)
|
6
|
+
self.keys.each do |k|
|
7
|
+
if k.to_s =~ Regexp.new(regex)
|
8
|
+
self.delete(k)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
# delete all keys in the given array
|
15
|
+
# and return the new hash
|
16
|
+
def delete_keys!(*keys)
|
17
|
+
keys.each do |k|
|
18
|
+
self.delete(k)
|
19
|
+
end
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
# params.dig('study_events',se.id.to_s,'eligible')
|
24
|
+
def dig(*args)
|
25
|
+
if args.length > 0 && self.keys.include?(args.first)
|
26
|
+
key = args.shift
|
27
|
+
if args.length > 0
|
28
|
+
if self[key].is_a?(Hash)
|
29
|
+
self[key].dig(*args)
|
30
|
+
else
|
31
|
+
nil # This shouldn't ever happen
|
32
|
+
end
|
33
|
+
else
|
34
|
+
self[key]
|
35
|
+
end
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# from http://iain.nl/writing-yaml-files
|
42
|
+
def deep_stringify_keys
|
43
|
+
new_hash = {}
|
44
|
+
self.each do |key, value|
|
45
|
+
new_hash.merge!(key.to_s => ( value.is_a?(Hash) ? value.deep_stringify_keys : value ))
|
46
|
+
end
|
47
|
+
new_hash # originally didn't return new_hash, which didn't work for me. returned self apparently.
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
Hash.send( :include, CommonLib::Hash )
|
File without changes
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module CommonLib::Object # :nodoc:
|
2
|
+
#
|
3
|
+
# # originally from ActiveSupport::Callbacks::Callback
|
4
|
+
## needs modified to actually work the way I'd like
|
5
|
+
## needs tests
|
6
|
+
## x(:some_method)
|
7
|
+
## x(Proc.new(....))
|
8
|
+
## x(lambda{...})
|
9
|
+
# # def evaluate_method(method, *args, &block)
|
10
|
+
# def evaluate_method(method, *args, &block)
|
11
|
+
# case method
|
12
|
+
# when Symbol
|
13
|
+
## I don't quite understand the shift (it fails)
|
14
|
+
## object = args.shift
|
15
|
+
## object.send(method, *args, &block)
|
16
|
+
# send(method, *args, &block)
|
17
|
+
# when String
|
18
|
+
# eval(method, args.first.instance_eval { binding })
|
19
|
+
# when Proc, Method
|
20
|
+
## fails
|
21
|
+
# method.call(*args, &block)
|
22
|
+
# else
|
23
|
+
# if method.respond_to?(kind)
|
24
|
+
# method.send(kind, *args, &block)
|
25
|
+
# else
|
26
|
+
# raise ArgumentError,
|
27
|
+
# "Callbacks must be a symbol denoting the method to call, a string to be evaluated, " +
|
28
|
+
# "a block to be invoked, or an object responding to the callback method."
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# alias_method :x, :evaluate_method
|
33
|
+
#
|
34
|
+
def to_boolean
|
35
|
+
# return [true, 'true', 1, '1', 't'].include?(
|
36
|
+
return ![nil, false, 'false', 0, '0', 'f'].include?(
|
37
|
+
( self.is_a?(String) ) ? self.downcase : self )
|
38
|
+
end
|
39
|
+
|
40
|
+
# looking for an explicit true
|
41
|
+
def true?
|
42
|
+
return [true, 'true', 1, '1', 't'].include?(
|
43
|
+
( self.is_a?(String) ) ? self.downcase : self )
|
44
|
+
end
|
45
|
+
|
46
|
+
# looking for an explicit false (not nil)
|
47
|
+
def false?
|
48
|
+
return [false, 'false', 0, '0', 'f'].include?(
|
49
|
+
( self.is_a?(String) ) ? self.downcase : self )
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
Object.send(:include, CommonLib::Object )
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CommonLib::String # :nodoc:
|
2
|
+
|
3
|
+
# Convert a query string like that in a URL
|
4
|
+
# to a Hash
|
5
|
+
def to_params_hash
|
6
|
+
h = HashWithIndifferentAccess.new
|
7
|
+
self.split('&').each do |p|
|
8
|
+
(k,v) = p.split('=',2)
|
9
|
+
h[k] = URI.decode(v)
|
10
|
+
end
|
11
|
+
return h
|
12
|
+
end
|
13
|
+
|
14
|
+
# Return self
|
15
|
+
def uniq
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
String.send( :include, CommonLib::String )
|
@@ -0,0 +1,129 @@
|
|
1
|
+
class CommonLib::TranslationTable
|
2
|
+
|
3
|
+
def self.[](key=nil)
|
4
|
+
short(key) || short(key.to_s.downcase) || value(key) || nil
|
5
|
+
end
|
6
|
+
|
7
|
+
# DO NOT MEMORIZE HERE. IT ENDS UP IN ALL SUBCLASSES
|
8
|
+
# Doesn't really seem necessary. It isn't that complicated.
|
9
|
+
|
10
|
+
# [1,2,999]
|
11
|
+
def self.valid_values
|
12
|
+
# @@valid_values ||= table.collect{ |x| x[:value] }
|
13
|
+
table.collect{ |x| x[:value] }
|
14
|
+
end
|
15
|
+
|
16
|
+
# [['Yes',1],['No',2],["Don't Know",999]]
|
17
|
+
def self.selector_options
|
18
|
+
# @@selector_options ||= table.collect{|x| [x[:long],x[:value]] }
|
19
|
+
table.collect{|x| [x[:long],x[:value]] }
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def self.short(key)
|
25
|
+
index = table.find_index{|x| x[:short] == key.to_s }
|
26
|
+
( index.nil? ) ? nil : table[index][:value]
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.value(key)
|
30
|
+
# used in testing and breaks in ruby 1.9.3 so next line is NEEDED!
|
31
|
+
return nil if key == :nil
|
32
|
+
index = table.find_index{|x| x[:value] == key.to_i }
|
33
|
+
( index.nil? ) ? nil : table[index][:long]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.table
|
37
|
+
[]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
class YNDK < CommonLib::TranslationTable
|
43
|
+
# unique translation table
|
44
|
+
def self.table
|
45
|
+
@@table ||= [
|
46
|
+
{ :value => 1, :short => 'yes', :long => "Yes" },
|
47
|
+
{ :value => 2, :short => 'no', :long => "No" },
|
48
|
+
{ :value => 999, :short => 'dk', :long => "Don't Know" }
|
49
|
+
]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
#
|
53
|
+
# YNDK[1] => 'Yes'
|
54
|
+
# YNDK['1'] => 'Yes'
|
55
|
+
# YNDK['yes'] => 1
|
56
|
+
# YNDK[:yes] => 1
|
57
|
+
# YNDK[:asdf] => nil
|
58
|
+
#
|
59
|
+
# YNDK[:Yes] => 1
|
60
|
+
# YNDK[:YES] => 1
|
61
|
+
#
|
62
|
+
# YNDK[:nil] => ???? # worked in ruby 1.8.7, errors in 1.9.3
|
63
|
+
# :nil.to_i => NoMethodError: undefined method `to_i' for :nil:Symbol
|
64
|
+
# what did it do? was that correct?
|
65
|
+
#
|
66
|
+
# in jruby
|
67
|
+
# jruby-1.5.1 :003 > :nil.to_i
|
68
|
+
# => 610
|
69
|
+
# which, in hind site, makes some sort of sense, but is NOT what is wanted
|
70
|
+
# same in ruby 1.8.7 (basically object id)
|
71
|
+
#
|
72
|
+
class YNODK < CommonLib::TranslationTable
|
73
|
+
def self.table
|
74
|
+
@@table ||= [
|
75
|
+
{ :value => 1, :short => 'yes', :long => "Yes" },
|
76
|
+
{ :value => 2, :short => 'no', :long => "No" },
|
77
|
+
{ :value => 3, :short => 'other', :long => "Other" },
|
78
|
+
{ :value => 999, :short => 'dk', :long => "Don't Know" }
|
79
|
+
]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
class YNRDK < CommonLib::TranslationTable
|
83
|
+
def self.table
|
84
|
+
@@table ||= [
|
85
|
+
{ :value => 1, :short => 'yes', :long => "Yes" },
|
86
|
+
{ :value => 2, :short => 'no', :long => "No" },
|
87
|
+
{ :value => 999, :short => 'dk', :long => "Don't Know" },
|
88
|
+
{ :value => 888, :short => 'refused', :long => "Refused" }
|
89
|
+
]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
class YNORDK < CommonLib::TranslationTable
|
93
|
+
def self.table
|
94
|
+
@@table ||= [
|
95
|
+
{ :value => 1, :short => 'yes', :long => "Yes" },
|
96
|
+
{ :value => 2, :short => 'no', :long => "No" },
|
97
|
+
{ :value => 3, :short => 'other', :long => "Other" },
|
98
|
+
{ :value => 999, :short => 'dk', :long => "Don't Know" },
|
99
|
+
{ :value => 888, :short => 'refused', :long => "Refused" }
|
100
|
+
]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
class ADNA < CommonLib::TranslationTable
|
104
|
+
def self.table
|
105
|
+
@@table ||= [
|
106
|
+
{ :value => 1, :short => 'agree', :long => "Agree" },
|
107
|
+
{ :value => 2, :short => 'disagree', :long => "Do Not Agree" },
|
108
|
+
{ :value => 555, :short => 'na', :long => "N/A" },
|
109
|
+
{ :value => 999, :short => 'dk', :long => "Don't Know" }
|
110
|
+
]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
class PADK < CommonLib::TranslationTable
|
114
|
+
def self.table
|
115
|
+
@@table ||= [
|
116
|
+
{ :value => 1, :short => 'present', :long => "Present" },
|
117
|
+
{ :value => 2, :short => 'absent', :long => "Absent" },
|
118
|
+
{ :value => 999, :short => 'dk', :long => "Don't Know" }
|
119
|
+
]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
class POSNEG < CommonLib::TranslationTable
|
123
|
+
def self.table
|
124
|
+
@@table ||= [
|
125
|
+
{ :value => 1, :short => 'pos', :long => "Positive" },
|
126
|
+
{ :value => 2, :short => 'neg', :long => "Negative" }
|
127
|
+
]
|
128
|
+
end
|
129
|
+
end
|
data/lib/tasks/csv.rake
ADDED
File without changes
|
@@ -0,0 +1,229 @@
|
|
1
|
+
class Hash
|
2
|
+
# From http://snippets.dzone.com/posts/show/5811
|
3
|
+
# Renaming and replacing the to_yaml function so it'll serialize hashes sorted (by their keys)
|
4
|
+
# Original function is in /usr/lib/ruby/1.8/yaml/rubytypes.rb
|
5
|
+
def to_ordered_yaml( opts = {} )
|
6
|
+
YAML::quick_emit( object_id, opts ) do |out|
|
7
|
+
out.map( taguri, to_yaml_style ) do |map|
|
8
|
+
sort.each do |k, v| # <-- here's my addition (the 'sort')
|
9
|
+
# The above sort, sorts the main yaml 'keys' or fixture labels.
|
10
|
+
# k is a fixture label here, eg. "pages_001"
|
11
|
+
# v is the attributes hash
|
12
|
+
# The hash attributes are NOT sorted, unfortunately.
|
13
|
+
# Still working on that one.
|
14
|
+
map.add( k, v )
|
15
|
+
|
16
|
+
|
17
|
+
#pages_001:
|
18
|
+
# position: 1
|
19
|
+
# menu_en: CCLS
|
20
|
+
# body_es:
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
namespace :app do
|
28
|
+
namespace :db do
|
29
|
+
|
30
|
+
desc "Create yml fixtures for given model in database\n" <<
|
31
|
+
"rake app:db:extract_fixtures_from pages"
|
32
|
+
task :extract_fixtures_from => :environment do
|
33
|
+
me = $*.shift
|
34
|
+
while( table_name = $*.shift )
|
35
|
+
# File.open("#{RAILS_ROOT}/db/#{table_name}.yml", 'w') do |file|
|
36
|
+
File.open("#{Rails.root}/db/#{table_name}.yml", 'w') do |file|
|
37
|
+
# data = table_name.singularize.capitalize.constantize.find(
|
38
|
+
# data = table_name.singularize.classify.constantize.find(
|
39
|
+
# :all).collect(&:attributes)
|
40
|
+
# Added unscoped to break any default scope and sort by id to add some order.
|
41
|
+
# Doesn't seem to actually work though. Still not sorted properly.
|
42
|
+
# Cause the result is an unordered hash. Bummer
|
43
|
+
# Still use unscoped, just in case there is a default scope with a limit.
|
44
|
+
#
|
45
|
+
data = table_name.singularize.classify.constantize.unscoped.order(
|
46
|
+
'id asc').collect(&:attributes)
|
47
|
+
|
48
|
+
# file.write data.inject({}) { |hash, record|
|
49
|
+
# record.delete('created_at')
|
50
|
+
# record.delete('updated_at')
|
51
|
+
# # so that it is really string sortable, add leading zeros
|
52
|
+
# hash["#{table_name}_#{sprintf('%03d',record['id'])}"] = record
|
53
|
+
# hash
|
54
|
+
# }.to_ordered_yaml
|
55
|
+
|
56
|
+
|
57
|
+
file.write recursive_hash_to_yml_string(
|
58
|
+
data.inject({}) { |hash, record|
|
59
|
+
record.delete('created_at')
|
60
|
+
record.delete('updated_at')
|
61
|
+
# so that it is really string sortable, add leading zeros
|
62
|
+
hash["#{table_name}_#{sprintf('%03d',record['id'])}"] = record
|
63
|
+
hash
|
64
|
+
}
|
65
|
+
)
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
exit # REQUIRED OR WILL ATTEMPT TO PROCESS ARGUMENTS AS RAKE TASK
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "Dump MYSQL table descriptions."
|
73
|
+
task :describe => :environment do
|
74
|
+
puts
|
75
|
+
puts "FYI: This task ONLY works on MYSQL databases."
|
76
|
+
puts
|
77
|
+
config = ActiveRecord::Base.connection.instance_variable_get(:@config)
|
78
|
+
#=> {:adapter=>"mysql", :host=>"localhost", :password=>nil, :username=>"root", :database=>"my_development", :encoding=>"utf8"}
|
79
|
+
|
80
|
+
# tables = ActiveRecord::Base.connection.execute('show tables;')
|
81
|
+
# while( table = tables.fetch_row ) do
|
82
|
+
# changes for MySQL2
|
83
|
+
tables = ActiveRecord::Base.connection.execute('show tables;').to_a.flatten.sort
|
84
|
+
while( table = tables.shift ) do
|
85
|
+
puts "Table: #{table}"
|
86
|
+
|
87
|
+
# may have to include host and port
|
88
|
+
system("mysql --table=true " <<
|
89
|
+
"--user=#{config[:username]} " <<
|
90
|
+
"--password='#{config[:password]}' " <<
|
91
|
+
"--execute='describe #{table}' " <<
|
92
|
+
config[:database]);
|
93
|
+
|
94
|
+
#
|
95
|
+
# mysql formats the table well so doing it by hand is something that
|
96
|
+
# will have to wait until I feel like wasting my time
|
97
|
+
#
|
98
|
+
# columns = ActiveRecord::Base.connection.execute("describe #{table};")
|
99
|
+
# while( column = columns.fetch_hash ) do
|
100
|
+
# puts column.keys Extra Default Null Type Field Key
|
101
|
+
# end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
desc "Calculate row size"
|
108
|
+
task :row_sizes => :environment do
|
109
|
+
puts
|
110
|
+
puts "FYI: This task ONLY works on MYSQL databases."
|
111
|
+
puts
|
112
|
+
config = ActiveRecord::Base.connection.instance_variable_get(:@config)
|
113
|
+
#=> {:adapter=>"mysql", :host=>"localhost", :password=>nil,
|
114
|
+
# :username=>"root", :database=>"my_development", :encoding=>"utf8"}
|
115
|
+
|
116
|
+
tables = ActiveRecord::Base.connection.execute('show tables;').to_a.flatten.sort
|
117
|
+
require 'nokogiri'
|
118
|
+
|
119
|
+
while( table = tables.shift ) do
|
120
|
+
# begin
|
121
|
+
# table = tables.first
|
122
|
+
puts "Table: #{table}"
|
123
|
+
|
124
|
+
# may have to include host and port
|
125
|
+
command = "mysql -X " <<
|
126
|
+
"--user=#{config[:username]} " <<
|
127
|
+
"--password='#{config[:password]}' " <<
|
128
|
+
"--execute='describe #{table}' " <<
|
129
|
+
config[:database]
|
130
|
+
|
131
|
+
# puts command
|
132
|
+
xml_doc = Nokogiri::XML(`#{command}`)
|
133
|
+
|
134
|
+
# <row>
|
135
|
+
# <field name="Field">id</field>
|
136
|
+
# <field name="Type">int(11)</field>
|
137
|
+
# <field name="Null">NO</field>
|
138
|
+
# <field name="Key">PRI</field>
|
139
|
+
# <field name="Default" xsi:nil="true" />
|
140
|
+
# <field name="Extra">auto_increment</field>
|
141
|
+
# </row>
|
142
|
+
table_size = 0
|
143
|
+
# http://www.w3schools.com/xpath/xpath_syntax.asp
|
144
|
+
xml_doc.xpath("//row/field[@name='Type']").each do |field|
|
145
|
+
field_size = case field.text
|
146
|
+
when /tinyint/ then 1
|
147
|
+
when /smallint/ then 2
|
148
|
+
when /mediumint/ then 3
|
149
|
+
when /bigint/ then 8
|
150
|
+
when /int/ then 4 # or integer (match last as would match above)
|
151
|
+
when /double/ then 4
|
152
|
+
when /float/ then 4
|
153
|
+
when /datetime/ then 8
|
154
|
+
when /timestamp/ then 4
|
155
|
+
when /year/ then 1
|
156
|
+
when /date/ then 3
|
157
|
+
when /time/ then 3
|
158
|
+
when /varchar\(\d+\)/ then field.text.scan(/varchar\((\d+)\)/).first.first.to_i
|
159
|
+
else 100 # just a guess
|
160
|
+
# puts field
|
161
|
+
end
|
162
|
+
# puts "#{field.name} - #{field.text} - #{field_size}"
|
163
|
+
table_size += field_size
|
164
|
+
end
|
165
|
+
puts table_size
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
end # namespace :db do
|
171
|
+
end # namespace :app do
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
# Would have to be very careful here as to not break anything.
|
178
|
+
# I don't know when to quote, add a | or a |- (or what the diff is)
|
179
|
+
|
180
|
+
|
181
|
+
#Possible yaml sort. Doesn't use the yaml library
|
182
|
+
|
183
|
+
#http://stackoverflow.com/questions/7275952/how-can-i-sort-yaml-files
|
184
|
+
# (modified)
|
185
|
+
|
186
|
+
|
187
|
+
# This WILL NOT WORK when the hash contains values that contains multi-line
|
188
|
+
# strings (like a text area). Somehow things need quoted or | or |- added.
|
189
|
+
|
190
|
+
# needed for escape
|
191
|
+
require 'yaml'
|
192
|
+
|
193
|
+
# doesn't exist in ruby 1.9.3,
|
194
|
+
# but seems ok with it being commented out.
|
195
|
+
# probably included in yaml.rb
|
196
|
+
#require 'yaml/encoding'
|
197
|
+
|
198
|
+
def recursive_hash_to_yml_string(hash, depth=0)
|
199
|
+
yml_string = ''
|
200
|
+
spacer = ""
|
201
|
+
depth.times { spacer += " "}
|
202
|
+
hash.keys.sort.each do |sorted_key|
|
203
|
+
yml_string += spacer + sorted_key + ": "
|
204
|
+
if hash[sorted_key].is_a?(Hash)
|
205
|
+
yml_string += "\n"
|
206
|
+
yml_string += recursive_hash_to_yml_string(hash[sorted_key], depth+1)
|
207
|
+
else
|
208
|
+
s = hash[sorted_key].to_s
|
209
|
+
if s.match("\n")
|
210
|
+
yml_string += "|-\n"
|
211
|
+
s.split(/\n/).each do |line|
|
212
|
+
yml_string += "#{spacer} #{line}\n"
|
213
|
+
end
|
214
|
+
else
|
215
|
+
# YAML.escape doesn't actually seem to escape as I would expect
|
216
|
+
# yml_string += "#{s.gsub(/([:>])/,"\\1")}\n"
|
217
|
+
# yml_string += "\"#{s}\"\n"
|
218
|
+
|
219
|
+
if s.match(/:/)
|
220
|
+
yml_string += "\"#{s}\"\n"
|
221
|
+
else
|
222
|
+
yml_string += "#{s}\n"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
yml_string
|
228
|
+
end
|
229
|
+
|