masterview 0.2.5 → 0.3.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.
- data/CHANGELOG +31 -1
- data/README +70 -69
- data/RELEASE_NOTES +70 -64
- data/Rakefile +26 -27
- data/TODO +13 -29
- data/doc/about.html +246 -0
- data/doc/configuration.html +49 -36
- data/doc/developer.html +423 -41
- data/doc/directives.html +139 -51
- data/doc/guide.html +19 -9
- data/doc/index.html +90 -224
- data/doc/installation.html +36 -28
- data/doc/media_list.html +30 -20
- data/doc/simple_diagram.html +3 -5
- data/doc/stylesheets/masterview.css +16 -1
- data/examples/rails_app_config/masterview/settings.rb +2 -1
- data/init.rb +1 -1
- data/lib/#ChangeLog# +6 -0
- data/lib/masterview/analyzer.rb +48 -34
- data/lib/masterview/attr_string_parser.rb +5 -1
- data/lib/masterview/case_insensitive_hash.rb +69 -0
- data/lib/masterview/{pathname_extensions.rb → core_ext/pathname.rb} +0 -0
- data/lib/masterview/{string_extensions.rb → core_ext/string.rb} +0 -0
- data/lib/masterview/deprecated/directive_base.rb +362 -0
- data/lib/masterview/directive_base.rb +201 -179
- data/lib/masterview/directive_dsl.rb +457 -0
- data/lib/masterview/directive_helpers.rb +28 -141
- data/lib/masterview/directive_load_path.rb +388 -0
- data/lib/masterview/directive_metadata.rb +377 -0
- data/lib/masterview/directive_registry.rb +259 -69
- data/lib/masterview/directives/.metadata +16 -0
- data/lib/masterview/directives/attr.rb +9 -8
- data/lib/masterview/directives/block.rb +11 -14
- data/lib/masterview/directives/check_box.rb +13 -18
- data/lib/masterview/directives/collection_select.rb +15 -29
- data/lib/masterview/directives/content.rb +9 -3
- data/lib/masterview/directives/else.rb +15 -13
- data/lib/masterview/directives/elsif.rb +14 -13
- data/lib/masterview/directives/eval.rb +20 -0
- data/lib/masterview/directives/form.rb +56 -9
- data/lib/masterview/directives/form_remote.rb +26 -0
- data/lib/masterview/directives/global_inline_erb.rb +10 -14
- data/lib/masterview/directives/hidden_field.rb +11 -20
- data/lib/masterview/directives/if.rb +13 -12
- data/lib/masterview/directives/image_tag.rb +20 -28
- data/lib/masterview/directives/import.rb +5 -12
- data/lib/masterview/directives/import_render.rb +7 -19
- data/lib/masterview/directives/insert_generated_comment.rb +8 -11
- data/lib/masterview/directives/javascript_include.rb +21 -12
- data/lib/masterview/directives/link_to.rb +14 -8
- data/lib/masterview/directives/link_to_function.rb +22 -0
- data/lib/masterview/directives/link_to_if.rb +15 -13
- data/lib/masterview/directives/link_to_remote.rb +13 -8
- data/lib/masterview/directives/omit_tag.rb +32 -16
- data/lib/masterview/directives/password_field.rb +10 -22
- data/lib/masterview/directives/radio_button.rb +11 -22
- data/lib/masterview/directives/replace.rb +7 -8
- data/lib/masterview/directives/select.rb +11 -24
- data/lib/masterview/directives/stylesheet_link.rb +20 -12
- data/lib/masterview/directives/submit.rb +11 -5
- data/lib/masterview/directives/text_area.rb +10 -23
- data/lib/masterview/directives/text_field.rb +10 -22
- data/lib/masterview/exceptions.rb +21 -0
- data/lib/masterview/extras/app/controllers/masterview_controller.rb +102 -75
- data/lib/masterview/extras/app/views/layouts/masterview_admin.rhtml +24 -23
- data/lib/masterview/extras/app/views/layouts/masterview_admin_config.rhtml +81 -0
- data/lib/masterview/extras/app/views/masterview/admin/configuration.rhtml +5 -1
- data/lib/masterview/extras/app/views/masterview/admin/create.rhtml +2 -2
- data/lib/masterview/extras/app/views/masterview/admin/directives.rhtml +5 -0
- data/lib/masterview/extras/app/views/masterview/admin/features.rhtml +5 -79
- data/lib/masterview/extras/app/views/masterview/admin/interact.rhtml +5 -0
- data/lib/masterview/extras/app/views/masterview/admin/list.rhtml +3 -71
- data/lib/masterview/extras/init_mv_admin_pages.rb +42 -23
- data/lib/masterview/filter_helpers.rb +26 -0
- data/lib/masterview/initializer.rb +99 -53
- data/lib/masterview/io.rb +19 -15
- data/lib/masterview/keyword_expander.rb +7 -2
- data/lib/masterview/masterview_info.rb +229 -23
- data/lib/masterview/masterview_version.rb +2 -2
- data/lib/masterview/parser.rb +275 -105
- data/lib/masterview/parser_helpers.rb +54 -0
- data/lib/masterview/rails_ext/action_controller_erb_direct.rb +29 -0
- data/lib/masterview/rails_ext/action_controller_reparse_checking.rb +27 -0
- data/lib/masterview/{extras/init_rails_erb_mv_direct.rb → rails_ext/action_view_erb_direct.rb} +12 -59
- data/lib/masterview/template_spec.rb +3 -2
- data/lib/masterview.rb +21 -12
- data/lib/rexml/parsers/baseparser_with_doctype_fix.rb +473 -0
- data/lib/rexml/parsers/sax2parser_with_doctype_fix.rb +243 -0
- data/test/directive_test_helper.rb +135 -0
- data/test/fixtures/directives/id_check.rb +18 -0
- data/test/fixtures/directives/test_directive_events.rb +70 -0
- data/test/test_helper.rb +18 -5
- data/test/tmp/views/layouts/product.rhtml +10 -10
- data/test/tmp/views/product/_form.rhtml +4 -4
- data/test/tmp/views/product/_product.rhtml +3 -3
- data/test/tmp/views/product/destroy.rhtml +5 -5
- data/test/tmp/views/product/edit.rhtml +4 -4
- data/test/tmp/views/product/list.rhtml +3 -3
- data/test/tmp/views/product/new.rhtml +4 -4
- data/test/tmp/views/product/show.rhtml +2 -2
- data/test/unit/attr_string_parser_test.rb +105 -0
- data/test/unit/case_insensitive_hash_mod_test.rb +104 -0
- data/test/unit/config_settings_test.rb +13 -1
- data/test/unit/default_generate_mio_filter_test.rb +3 -3
- data/test/unit/deprecated_directive_base_test.rb +30 -0
- data/test/unit/directive_attr_test.rb +111 -35
- data/test/unit/directive_base_test.rb +520 -1
- data/test/unit/directive_block_test.rb +30 -22
- data/test/unit/directive_content_test.rb +24 -11
- data/test/unit/directive_else_test.rb +18 -15
- data/test/unit/directive_elsif_test.rb +17 -15
- data/test/unit/directive_form_remote_test.rb +59 -0
- data/test/unit/directive_form_test.rb +31 -39
- data/test/unit/directive_global_inline_erb_test.rb +28 -17
- data/test/unit/directive_grid_test_notready.rb +38 -0
- data/test/unit/directive_helpers_test.rb +39 -0
- data/test/unit/directive_hidden_field_test.rb +44 -29
- data/test/unit/directive_if_test.rb +10 -7
- data/test/unit/directive_image_tag_test.rb +69 -61
- data/test/unit/directive_import_render_test.rb +28 -38
- data/test/unit/directive_import_test.rb +16 -14
- data/test/unit/directive_insert_generated_comment_test.rb +32 -0
- data/test/unit/directive_javascript_include_test.rb +40 -43
- data/test/unit/directive_link_to_function_test.rb +40 -0
- data/test/unit/directive_link_to_if_test.rb +52 -12
- data/test/unit/directive_link_to_remote_test.rb +58 -0
- data/test/unit/directive_link_to_test.rb +46 -31
- data/test/unit/directive_load_path_test.rb +257 -0
- data/test/unit/directive_metadata_test.rb +313 -0
- data/test/unit/directive_omit_tag_test.rb +73 -21
- data/test/unit/directive_password_field_test.rb +44 -38
- data/test/unit/directive_registry_test.rb +44 -0
- data/test/unit/directive_replace_test.rb +28 -12
- data/test/unit/directive_stylesheet_link_test.rb +43 -36
- data/test/unit/directive_submit_test.rb +29 -30
- data/test/unit/directive_text_area_test.rb +40 -36
- data/test/unit/directive_text_field_test.rb +44 -38
- data/test/unit/example_directive_child_events_test.rb +41 -0
- data/test/unit/example_test.rb +31 -4
- data/test/unit/file_mio_test.rb +18 -13
- data/test/unit/filter_helpers_test.rb +10 -8
- data/test/unit/find_directive_parent_test.rb +174 -0
- data/test/unit/keyword_expander_test.rb +4 -2
- data/test/unit/mio_test.rb +18 -11
- data/test/unit/mtime_string_hash_mio_tree_test.rb +5 -1
- data/test/unit/parser_test.rb +41 -29
- data/test/unit/pathname_extensions_test.rb +1 -1
- data/test/unit/run_parser_test.rb +2 -2
- data/test/unit/simplified_directive_base_test.rb +256 -0
- data/test/unit/string_hash_mio_test.rb +5 -1
- data/test/unit/template_file_watcher_test.rb +2 -2
- data/test/unit/template_test.rb +221 -46
- metadata +86 -45
- data/lib/masterview/directives/testfilter.rb +0 -55
- data/lib/masterview/extras/init_rails_reparse_checking.rb +0 -62
@@ -0,0 +1,362 @@
|
|
1
|
+
module MasterView
|
2
|
+
|
3
|
+
# Namespace module for built-in directive implementations
|
4
|
+
# that are standard with the MasterView template engine.
|
5
|
+
#
|
6
|
+
module Directives
|
7
|
+
end
|
8
|
+
|
9
|
+
# THIS CLASS IS DEPRECATED!!! UPGRADE DIRECTIVES TO USE NEW DirectiveBase
|
10
|
+
#
|
11
|
+
# Base class for directive implementations.
|
12
|
+
#
|
13
|
+
# The standard technique for implementing a directive
|
14
|
+
# is to subclass DirectiveBase. The builtin
|
15
|
+
# MasterView directives are implemented in
|
16
|
+
# module namespace MasterView::Directives.
|
17
|
+
#
|
18
|
+
# If you create a directive implementation class
|
19
|
+
# elsewhere in the class hierarchy, it is recommended
|
20
|
+
# that you include the DirectiveHelpers mixin.
|
21
|
+
# If you do not include the PluginLoadTracking mixin,
|
22
|
+
# you will need to manually register your directive
|
23
|
+
# class using the MasterView.register_directive service.
|
24
|
+
# either the PluginLoadTracking mixin or
|
25
|
+
#
|
26
|
+
#
|
27
|
+
#--
|
28
|
+
#TODO: add docs here on responsibilities and techniques for
|
29
|
+
# implementing directives. Subclass DirectiveBase, define
|
30
|
+
# within MasterView::Directives module namespace.
|
31
|
+
#
|
32
|
+
# mumble - class methods:
|
33
|
+
# attr_name is the directive's attribute markup name - def. is class name
|
34
|
+
# full_attr_name(ns) is the qualified name (name-space prefixed)
|
35
|
+
#
|
36
|
+
# Directive can optionally implement class method :on_load to initialize
|
37
|
+
# itself prior to processed for the directive registry
|
38
|
+
#
|
39
|
+
#TODO: establish protocol convention for additional namespaces
|
40
|
+
#
|
41
|
+
# mumble: :global_directive? predicate indicates... what?? (inline erb)
|
42
|
+
#
|
43
|
+
# Directives implement <code>priority</code> to control the processing
|
44
|
+
# order when multiple directive attributes are used on a template
|
45
|
+
# document element.
|
46
|
+
#
|
47
|
+
#TODO: document the priority hierarchy and convention for level usage
|
48
|
+
#
|
49
|
+
# Discuss operational context: describe how/when MasterView parser
|
50
|
+
# invokes a directive handler in the course of parsing the elements
|
51
|
+
# and attributes of a template document node hierarchy.
|
52
|
+
# Notion of directive call stack; what state is the world in and
|
53
|
+
# information is available to a directive when invoked;
|
54
|
+
# what services are available in order to produce some effect
|
55
|
+
# on the results of the template parse.
|
56
|
+
#
|
57
|
+
# Two general flavors on content directives: those which operate on attribute
|
58
|
+
# values of the containing element and those which operate on the
|
59
|
+
# entire containing element, sometimes by supplying or modifying its
|
60
|
+
# content, in other cases by replacing the template element with something
|
61
|
+
# else.
|
62
|
+
#
|
63
|
+
# Third flavor: eval-only directive. Expression which is evaluate for its
|
64
|
+
# effect on the directive processing context or the overall state of processing
|
65
|
+
# the template document element tree.
|
66
|
+
#
|
67
|
+
# Directive implementation typically wants to implement either or both of
|
68
|
+
# the methods <code>stag(dcs)</code> and <code>etag(dcs)</code> to hook
|
69
|
+
# up its processing on the start/end tags of the element on which the
|
70
|
+
# attribute is defined.
|
71
|
+
#
|
72
|
+
# When a directive attribute is used on a template document element,
|
73
|
+
# the directive class is instantiated with the attribute_value provided
|
74
|
+
# to its constructure. All directives used on an element are sorted
|
75
|
+
# into processing order according to their <code>priority</code>
|
76
|
+
# (default is <code>Medium</code>. The directive processor is invoked
|
77
|
+
# when the element start tag is encountered and when the element end
|
78
|
+
# tag is completed, allowing the implementation to control when and
|
79
|
+
# how its processing is hooked up to effect the template output.
|
80
|
+
#++
|
81
|
+
#
|
82
|
+
class DirectiveBaseOld
|
83
|
+
include PluginLoadTracking
|
84
|
+
include DirectiveHelpers
|
85
|
+
|
86
|
+
# Register a class manually without regard to whether it inherits from DirectiveBase.
|
87
|
+
# Classes which derive from DirectiveBase will automatically be registered as they are
|
88
|
+
# loaded.
|
89
|
+
def self.register_directive(directive_class)
|
90
|
+
#ISSUE: do we really need both PluginLoadTracking.register_class
|
91
|
+
#and DirectiveBase.register_directive, in addition to MasterView.register_directive???
|
92
|
+
#[DJL 04-Jul-2006]
|
93
|
+
MasterView.register_directive(directive_class)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the fully qualified attribute name of the directive,
|
97
|
+
# consisting of the directive namespace and the directive attribute name.
|
98
|
+
#
|
99
|
+
# The default MasterView namespace_prefix is used if the directive does not
|
100
|
+
# specify a separate namespace.
|
101
|
+
#
|
102
|
+
#--
|
103
|
+
#TODO: clarify the mechanism by which alternate namespaces are defined.
|
104
|
+
# Is this done by a code value or configured as part of the directory
|
105
|
+
# path specifications, or some combination thereof to allow ovverides
|
106
|
+
# in the event of namespace collisions?
|
107
|
+
#++
|
108
|
+
#
|
109
|
+
def self.full_attr_name( namespace_prefix )
|
110
|
+
#TODO: fix this so that directives can override to define their own namespace separate from mv:
|
111
|
+
namespace_prefix + self.attr_name
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns the attribute name of the directive.
|
115
|
+
#
|
116
|
+
# Use full_attr_name to obtain the fully-qualified name
|
117
|
+
# of the directive attribute with the qualifying namespace prefix.
|
118
|
+
#
|
119
|
+
# The default attribute name of a directive is formed
|
120
|
+
# from the simple class name (without any module prefix qualifier),
|
121
|
+
# with the first character downcased.
|
122
|
+
#
|
123
|
+
def self.attr_name()
|
124
|
+
self.default_attr_name()
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.default_attr_name() #:nodoc:
|
128
|
+
self.name.split(':').last.downcase_first_letter
|
129
|
+
end
|
130
|
+
|
131
|
+
# Construct a directive processor for the attribute_value
|
132
|
+
# of a directive attribute on a document template element.
|
133
|
+
#
|
134
|
+
def initialize(attribute_value)
|
135
|
+
@attribute_value = attribute_value
|
136
|
+
end
|
137
|
+
|
138
|
+
#if this method exists, it will be called by renderer to save directive_call_stack before each method call
|
139
|
+
def save_directive_call_stack(directive_call_stack)
|
140
|
+
@directive_call_stack = directive_call_stack
|
141
|
+
end
|
142
|
+
|
143
|
+
# Returns the directive's attribute value string being processed.
|
144
|
+
def attr_value
|
145
|
+
@attribute_value
|
146
|
+
end
|
147
|
+
|
148
|
+
# Set the directive's attribute value string to be processed.
|
149
|
+
def attr_value=(attribute_value)
|
150
|
+
@attribute_value = attribute_value
|
151
|
+
end
|
152
|
+
|
153
|
+
#get attribute hash from tag
|
154
|
+
def attrs
|
155
|
+
@directive_call_stack.context[:tag].attributes
|
156
|
+
end
|
157
|
+
|
158
|
+
#set attribute hash for tag
|
159
|
+
def attrs=(attributes)
|
160
|
+
@directive_call_stack.context[:tag].attributes = attributes
|
161
|
+
end
|
162
|
+
|
163
|
+
#get attribute hash with lowercased keys and values, and cache it
|
164
|
+
def attrs_lckv
|
165
|
+
@attrs_lckv ||= lowercase_attribute_keys_and_values(attrs)
|
166
|
+
end
|
167
|
+
|
168
|
+
#get attribute hash with lowercased keys (and original values) and cache it
|
169
|
+
def attrs_lck
|
170
|
+
@attrs_lck ||= lowercase_attribute_keys(attrs)
|
171
|
+
end
|
172
|
+
|
173
|
+
#returns true if the value for lckey of the attribute hash with lowercased keys and values
|
174
|
+
#matches (lowercase) lcmatch string
|
175
|
+
def attr_lckv_matches(lckey, lcmatch)
|
176
|
+
(attrs_lckv[lckey] && attrs_lckv[lckey] == lcmatch.downcase) ? true : false
|
177
|
+
end
|
178
|
+
|
179
|
+
#DEPRECATED - going away
|
180
|
+
#output '<% '+str+' %>'
|
181
|
+
def erb(str) #:nodoc:
|
182
|
+
#ISSUE: convert clients to erb_eval and drop. Ya oughta have a point of view. [DJL 04-Jul-2006]
|
183
|
+
ERB_EVAL_START + str + ERB_EVAL_END
|
184
|
+
end
|
185
|
+
|
186
|
+
# Compose an Erb expression which produces content in the containing document.
|
187
|
+
# The expression may also have effects on the processing context of
|
188
|
+
# the template document
|
189
|
+
#
|
190
|
+
# output '<%= '+str+' %>
|
191
|
+
#
|
192
|
+
def erb_content(str)
|
193
|
+
ERB_CONTENT_START + str + ERB_CONTENT_END
|
194
|
+
end
|
195
|
+
|
196
|
+
# Compose an Erb expression which is evaluated for its effect on the processing context
|
197
|
+
# but does not produce content in the containing document.
|
198
|
+
#
|
199
|
+
# output '<% '+str+' %>'
|
200
|
+
#
|
201
|
+
def erb_eval(str)
|
202
|
+
ERB_EVAL_START + str + ERB_EVAL_END
|
203
|
+
end
|
204
|
+
|
205
|
+
#get tag_name
|
206
|
+
def tag_name
|
207
|
+
@directive_call_stack.context[:tag].tag_name
|
208
|
+
end
|
209
|
+
|
210
|
+
#set tag_name
|
211
|
+
def tag_name=(tag_name)
|
212
|
+
@directive_call_stack.context[:tag].tag_name = tag_name
|
213
|
+
end
|
214
|
+
|
215
|
+
#inside characters, cdata, or comment you can call this to get the characters passed
|
216
|
+
def data
|
217
|
+
@directive_call_stack.context[:content_part]
|
218
|
+
end
|
219
|
+
|
220
|
+
#set the data that will be passed to characters, cdata, or comment directives
|
221
|
+
def data=(data)
|
222
|
+
@directive_call_stack.context[:content_part]=data
|
223
|
+
end
|
224
|
+
|
225
|
+
# rolled up content from all children of the tag, note this will not be complete until hitting the end tag method :etag
|
226
|
+
def content
|
227
|
+
@directive_call_stack.context[:tag].content
|
228
|
+
end
|
229
|
+
|
230
|
+
#return rolled up content from all children as string, note this will not be complete until hitting the end tag method :etag
|
231
|
+
def content_str
|
232
|
+
content = @directive_call_stack.context[:tag].content
|
233
|
+
content = content.join if content.respond_to? :join
|
234
|
+
content
|
235
|
+
end
|
236
|
+
|
237
|
+
# replace the content from all children with a new value
|
238
|
+
def content=(content)
|
239
|
+
@directive_call_stack.context[:tag].content = content
|
240
|
+
end
|
241
|
+
|
242
|
+
def remove_strings_from_attr_value!
|
243
|
+
self.attr_value = remove_prepended_strings(attr_value)
|
244
|
+
end
|
245
|
+
|
246
|
+
#prepend string to attribute value adding a comma if attribute value was not empty
|
247
|
+
def prepend_to_attr_value!(str)
|
248
|
+
return attr_value if str.nil? || str.strip.empty?
|
249
|
+
av = str
|
250
|
+
av << ', ' << attr_value unless attr_value.strip.empty?
|
251
|
+
self.attr_value = av
|
252
|
+
end
|
253
|
+
|
254
|
+
#append string to attribute value adding a comma if attribute value was not empty
|
255
|
+
def append_to_attr_value!(str)
|
256
|
+
return attr_value if str.nil? || str.strip.empty?
|
257
|
+
av = attr_value
|
258
|
+
av << ', ' unless av.strip.empty?
|
259
|
+
av << str
|
260
|
+
self.attr_value = av
|
261
|
+
end
|
262
|
+
|
263
|
+
#merge merge_hash into hashes stored in attribute_value string
|
264
|
+
#hash_index is the zero based index of the hash you want to add to
|
265
|
+
def merge_hash_attr_value!(hash_index, merge_hash)
|
266
|
+
self.attr_value = merge_into_embedded_hash(attr_value, hash_index, merge_hash)
|
267
|
+
end
|
268
|
+
|
269
|
+
#calls non-evaling parse to split into string arguments
|
270
|
+
def parse_attr_value
|
271
|
+
parse(attr_value)
|
272
|
+
end
|
273
|
+
|
274
|
+
# check for common html options and return the hash
|
275
|
+
def common_html_options(attrs_lck)
|
276
|
+
options = {}
|
277
|
+
options[:id] = attrs_lck['id'] if attrs_lck['id']
|
278
|
+
options[:class] = attrs_lck['class'] if attrs_lck['class']
|
279
|
+
options[:style] = attrs_lck['style'] if attrs_lck['style']
|
280
|
+
options[:tabindex] = attrs_lck['tabindex'] if attrs_lck['tabindex']
|
281
|
+
options[:accesskey] = attrs_lck['accesskey'] if attrs_lck['accesskey']
|
282
|
+
options[:disabled] = true if attrs_lck['disabled']
|
283
|
+
options[:readonly] = true if attrs_lck['readonly']
|
284
|
+
options
|
285
|
+
end
|
286
|
+
|
287
|
+
|
288
|
+
# deprecated methods from DirectiveHelpers
|
289
|
+
#DEPRECATED
|
290
|
+
#remove any strings that were prepended to the hashes, typically these are overridden by other values, so
|
291
|
+
#we need to strip them off leaving only the hashes, returns a string with only hashes
|
292
|
+
def remove_prepended_strings(full_string)
|
293
|
+
return full_string if full_string.nil? || full_string.strip.empty?
|
294
|
+
hashes = full_string.scan( /(\{?)\s*(\S+\s*=>.*)/ ).flatten
|
295
|
+
hashes.join.strip
|
296
|
+
end
|
297
|
+
|
298
|
+
#DEPRECATED
|
299
|
+
#merge hash_to_merge values into the hash contained in the full_string, hash_arg is zero based index of which
|
300
|
+
#hash this needes to be merged to if there are multiple ones.
|
301
|
+
def merge_into_embedded_hash(full_string, hash_arg, hash_to_merge)
|
302
|
+
return full_string if hash_to_merge.empty?
|
303
|
+
full_string ||= ""
|
304
|
+
sorted_hash_to_merge = hash_to_merge.sort { |a,b| a[0].to_s <=> b[0].to_s } #sort, remember the keys might be symbols so use to_s
|
305
|
+
str_to_merge = sorted_hash_to_merge.collect{ |h,v| "#{h.inspect} => #{v.inspect}" }.join(', ')
|
306
|
+
|
307
|
+
hashes = full_string.scan( /(\{?[^{}]+=>[^{}]+\}?)\s*,?\s*/ ).flatten
|
308
|
+
hash_str = hashes[hash_arg] #be careful to use methods to update string in place or else put back in hash
|
309
|
+
|
310
|
+
if hash_str.nil?
|
311
|
+
hashes.each do |v| #make sure each prior hash has brackets, since we are adding a hash
|
312
|
+
unless v.index '}'
|
313
|
+
v.insert(0, '{')
|
314
|
+
v.insert(-1, '}')
|
315
|
+
end
|
316
|
+
end
|
317
|
+
hashes[hash_arg] = hash_str = ""
|
318
|
+
end
|
319
|
+
|
320
|
+
closing_brack = hash_str.index '}'
|
321
|
+
if closing_brack
|
322
|
+
hash_str.insert(closing_brack, ', '+str_to_merge)
|
323
|
+
else
|
324
|
+
hash_str << ', ' unless hash_str.empty?
|
325
|
+
hash_str << str_to_merge
|
326
|
+
end
|
327
|
+
|
328
|
+
hashes.join(', ')
|
329
|
+
end
|
330
|
+
|
331
|
+
#DEPRECATED
|
332
|
+
#return attributes with lowercase keys
|
333
|
+
def lowercase_attribute_keys(attributes)
|
334
|
+
lcattrs = {}
|
335
|
+
attributes.each { |k,v| lcattrs[k.downcase] = v }
|
336
|
+
lcattrs
|
337
|
+
end
|
338
|
+
|
339
|
+
#DEPRECATED
|
340
|
+
#return attributes with lowercase keys and values
|
341
|
+
def lowercase_attribute_keys_and_values(attributes)
|
342
|
+
lcattrs = {}
|
343
|
+
attributes.each { |k,v| lcattrs[k.downcase] = v.downcase }
|
344
|
+
lcattrs
|
345
|
+
end
|
346
|
+
|
347
|
+
#DEPRECATED
|
348
|
+
#using hash, symbolize keys, sort keys, serialize to string
|
349
|
+
def symbolize_sort_and_serialize_hash_to_str(hash)
|
350
|
+
symbolized = {}
|
351
|
+
hash.each{ |k,v| symbolized[k.to_sym] = v } #symbolize
|
352
|
+
sorted = symbolized.sort{ |a,b| a[0].to_s <=> b[0].to_s } # sort the keys
|
353
|
+
sorted_strings = sorted.collect{ |k,v| "#{k.inspect} => '#{v}'"} # create strings
|
354
|
+
sorted_strings.join(', ') # finally combine them
|
355
|
+
end
|
356
|
+
|
357
|
+
|
358
|
+
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
end
|