ruote 2.3.0.1 → 2.3.0.2
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.txt +23 -0
- data/CREDITS.txt +4 -0
- data/LICENSE.txt +1 -1
- data/lib/ruote.rb +2 -0
- data/lib/ruote/context.rb +2 -1
- data/lib/ruote/dashboard.rb +169 -13
- data/lib/ruote/dboard/mutation.rb +282 -0
- data/lib/ruote/dboard/process_error.rb +1 -1
- data/lib/ruote/dboard/process_status.rb +61 -48
- data/lib/ruote/engine.rb +1 -1
- data/lib/ruote/exp/command.rb +1 -1
- data/lib/ruote/exp/commanded.rb +1 -1
- data/lib/ruote/exp/condition.rb +2 -1
- data/lib/ruote/exp/fe_add_branches.rb +1 -1
- data/lib/ruote/exp/fe_apply.rb +1 -1
- data/lib/ruote/exp/fe_await.rb +97 -48
- data/lib/ruote/exp/fe_cancel_process.rb +1 -1
- data/lib/ruote/exp/fe_command.rb +2 -3
- data/lib/ruote/exp/fe_concurrence.rb +162 -66
- data/lib/ruote/exp/fe_concurrent_iterator.rb +25 -7
- data/lib/ruote/exp/fe_cron.rb +1 -1
- data/lib/ruote/exp/fe_cursor.rb +10 -11
- data/lib/ruote/exp/fe_define.rb +1 -1
- data/lib/ruote/exp/fe_echo.rb +1 -1
- data/lib/ruote/exp/fe_equals.rb +1 -1
- data/lib/ruote/exp/fe_error.rb +1 -1
- data/lib/ruote/exp/fe_filter.rb +1 -1
- data/lib/ruote/exp/fe_forget.rb +1 -1
- data/lib/ruote/exp/fe_given.rb +1 -1
- data/lib/ruote/exp/fe_if.rb +87 -7
- data/lib/ruote/exp/fe_inc.rb +1 -1
- data/lib/ruote/exp/fe_iterator.rb +1 -1
- data/lib/ruote/exp/fe_listen.rb +1 -1
- data/lib/ruote/exp/fe_lose.rb +1 -1
- data/lib/ruote/exp/fe_noop.rb +1 -1
- data/lib/ruote/exp/fe_on_error.rb +1 -1
- data/lib/ruote/exp/fe_once.rb +1 -1
- data/lib/ruote/exp/fe_participant.rb +49 -16
- data/lib/ruote/exp/fe_read.rb +1 -1
- data/lib/ruote/exp/fe_redo.rb +1 -1
- data/lib/ruote/exp/fe_ref.rb +1 -1
- data/lib/ruote/exp/fe_registerp.rb +1 -1
- data/lib/ruote/exp/fe_reserve.rb +1 -1
- data/lib/ruote/exp/fe_restore.rb +1 -7
- data/lib/ruote/exp/fe_save.rb +1 -1
- data/lib/ruote/exp/fe_sequence.rb +1 -1
- data/lib/ruote/exp/fe_set.rb +1 -1
- data/lib/ruote/exp/fe_stall.rb +1 -1
- data/lib/ruote/exp/fe_subprocess.rb +1 -1
- data/lib/ruote/exp/fe_that.rb +1 -1
- data/lib/ruote/exp/fe_undo.rb +1 -1
- data/lib/ruote/exp/fe_unregisterp.rb +1 -1
- data/lib/ruote/exp/fe_wait.rb +1 -1
- data/lib/ruote/exp/flow_expression.rb +117 -8
- data/lib/ruote/exp/iterator.rb +1 -1
- data/lib/ruote/exp/ro_attributes.rb +1 -1
- data/lib/ruote/exp/ro_filters.rb +1 -1
- data/lib/ruote/exp/ro_on_x.rb +4 -2
- data/lib/ruote/exp/ro_persist.rb +1 -1
- data/lib/ruote/exp/ro_timers.rb +1 -1
- data/lib/ruote/exp/ro_variables.rb +1 -1
- data/lib/ruote/extract.rb +125 -0
- data/lib/ruote/fei.rb +10 -73
- data/lib/ruote/id/mnemo_wfid_generator.rb +1 -1
- data/lib/ruote/id/wfid_generator.rb +1 -1
- data/lib/ruote/log/default_history.rb +17 -3
- data/lib/ruote/log/fancy_printing.rb +12 -32
- data/lib/ruote/log/storage_history.rb +1 -1
- data/lib/ruote/log/wait_logger.rb +15 -7
- data/lib/ruote/merge.rb +123 -0
- data/lib/ruote/observer.rb +1 -1
- data/lib/ruote/part/block_participant.rb +1 -1
- data/lib/ruote/part/code_participant.rb +1 -1
- data/lib/ruote/part/engine_participant.rb +1 -1
- data/lib/ruote/part/local_participant.rb +9 -1
- data/lib/ruote/part/no_op_participant.rb +1 -1
- data/lib/ruote/part/null_participant.rb +1 -1
- data/lib/ruote/part/participant.rb +1 -1
- data/lib/ruote/part/rev_participant.rb +1 -1
- data/lib/ruote/part/smtp_participant.rb +1 -1
- data/lib/ruote/part/storage_participant.rb +18 -1
- data/lib/ruote/part/template.rb +1 -1
- data/lib/ruote/reader.rb +1 -1
- data/lib/ruote/reader/json.rb +1 -1
- data/lib/ruote/reader/radial.rb +4 -4
- data/lib/ruote/reader/ruby_dsl.rb +1 -1
- data/lib/ruote/reader/xml.rb +1 -1
- data/lib/ruote/receiver/base.rb +13 -1
- data/lib/ruote/storage/base.rb +8 -14
- data/lib/ruote/storage/composite_storage.rb +1 -1
- data/lib/ruote/storage/fs_storage.rb +1 -1
- data/lib/ruote/storage/hash_storage.rb +2 -1
- data/lib/ruote/svc/dispatch_pool.rb +29 -18
- data/lib/ruote/svc/dollar_sub.rb +5 -8
- data/lib/ruote/svc/error_handler.rb +1 -1
- data/lib/ruote/svc/expression_map.rb +1 -1
- data/lib/ruote/svc/participant_list.rb +8 -5
- data/lib/ruote/svc/tracker.rb +154 -56
- data/lib/ruote/svc/treechecker.rb +1 -1
- data/lib/ruote/tree_dot.rb +1 -1
- data/lib/ruote/util/deep.rb +4 -2
- data/lib/ruote/util/filter.rb +1 -1
- data/lib/ruote/util/hashdot.rb +1 -1
- data/lib/ruote/util/look.rb +1 -1
- data/lib/ruote/util/lookup.rb +1 -1
- data/lib/ruote/util/misc.rb +51 -1
- data/lib/ruote/util/mpatch.rb +1 -1
- data/lib/ruote/util/ometa.rb +1 -1
- data/lib/ruote/util/subprocess.rb +1 -1
- data/lib/ruote/util/time.rb +3 -3
- data/lib/ruote/util/tree.rb +43 -4
- data/lib/ruote/version.rb +2 -2
- data/lib/ruote/worker.rb +30 -18
- data/lib/ruote/workitem.rb +1 -1
- data/ruote.gemspec +6 -2
- data/test/functional/base.rb +0 -1
- data/test/functional/concurrent_base.rb +1 -1
- data/test/functional/eft_14_cursor.rb +42 -52
- data/test/functional/eft_16_if.rb +24 -16
- data/test/functional/eft_18_concurrent_iterator.rb +31 -1
- data/test/functional/eft_6_concurrence.rb +149 -34
- data/test/functional/ft_10_dollar.rb +14 -30
- data/test/functional/ft_12_launchitem.rb +15 -0
- data/test/functional/ft_1_process_status.rb +62 -13
- data/test/functional/ft_20_storage_participant.rb +25 -0
- data/test/functional/ft_38_participant_more.rb +1 -1
- data/test/functional/ft_42_storage_copy.rb +1 -3
- data/test/functional/ft_43_participant_on_reply.rb +63 -5
- data/test/functional/ft_66_flank.rb +41 -0
- data/test/functional/ft_6_on_cancel.rb +9 -18
- data/test/functional/ft_71_retries.rb +25 -12
- data/test/functional/ft_79_attach.rb +138 -0
- data/test/functional/ft_7_tags.rb +27 -0
- data/test/functional/ft_80_pause_on_apply.rb +64 -0
- data/test/functional/ft_81_mutation.rb +417 -0
- data/test/functional/ft_82_await_attribute.rb +84 -0
- data/test/functional/ft_83_trackers.rb +79 -0
- data/test/functional/storage.rb +3 -4
- data/test/unit/ut_12_wait_logger.rb +41 -3
- data/test/unit/ut_15_util.rb +30 -0
- data/test/unit/ut_17_merge.rb +54 -53
- data/test/unit/ut_1_fei.rb +2 -2
- data/test/unit/ut_24_radial_reader.rb +7 -0
- data/test/unit/ut_26_deep.rb +14 -0
- data/test/unit/ut_5_tree.rb +38 -28
- metadata +206 -169
- data/couch_url.txt +0 -1
- data/lib/ruote/exp/merge.rb +0 -134
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -173,17 +173,18 @@ module Ruote
|
|
173
173
|
pinfo = participant_name.is_a?(String) ?
|
174
174
|
lookup_info(participant_name, workitem) : participant_name
|
175
175
|
|
176
|
-
pinfo
|
177
|
-
instantiate(pinfo, opts) : nil
|
176
|
+
instantiate(pinfo, opts)
|
178
177
|
end
|
179
178
|
|
180
|
-
# Given a participant name, returns
|
179
|
+
# Given a participant name, returns participant details.
|
181
180
|
#
|
182
181
|
# Returns nil if there is no participant registered that covers the given
|
183
182
|
# participant name.
|
184
183
|
#
|
185
184
|
def lookup_info(pname, workitem)
|
186
185
|
|
186
|
+
return nil unless pname
|
187
|
+
|
187
188
|
wi = workitem ?
|
188
189
|
Ruote::Workitem.new(workitem.merge('participant_name' => pname)) :
|
189
190
|
nil
|
@@ -205,10 +206,12 @@ module Ruote
|
|
205
206
|
nil
|
206
207
|
end
|
207
208
|
|
208
|
-
# Returns an instance of a participant
|
209
|
+
# Returns an instance of a participant.
|
209
210
|
#
|
210
211
|
def instantiate(pinfo, opts={})
|
211
212
|
|
213
|
+
return nil unless pinfo
|
214
|
+
|
212
215
|
pa_class_name, options = pinfo
|
213
216
|
|
214
217
|
if rp = options['require_path']
|
data/lib/ruote/svc/tracker.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -39,18 +39,109 @@ module Ruote
|
|
39
39
|
@context = context
|
40
40
|
end
|
41
41
|
|
42
|
-
# The
|
43
|
-
#
|
42
|
+
# The worker calls this method via the context before each msg gets
|
43
|
+
# processed.
|
44
44
|
#
|
45
|
-
def
|
45
|
+
def on_pre_msg(msg)
|
46
|
+
|
47
|
+
on_message(true, msg)
|
48
|
+
end
|
49
|
+
|
50
|
+
# The worker calls this method via the context after each successful
|
51
|
+
# msg processing.
|
52
|
+
#
|
53
|
+
def on_msg(msg)
|
54
|
+
|
55
|
+
on_message(false, msg)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Adds a tracker (usually when a 'listen' expression gets applied).
|
59
|
+
#
|
60
|
+
# The tracker_id may be nil (one will then get generated).
|
61
|
+
#
|
62
|
+
# Returns the tracker_id.
|
63
|
+
#
|
64
|
+
def add_tracker(wfid, action, tracker_id, conditions, msg)
|
65
|
+
|
66
|
+
tracker_id ||= [
|
67
|
+
'tracker', wfid, action,
|
68
|
+
Ruote.generate_subid(conditions.hash.to_s + msg.hash.to_s)
|
69
|
+
].collect(&:to_s).join('_')
|
70
|
+
|
71
|
+
conditions =
|
72
|
+
conditions && conditions.remap { |(k, v), h| h[k] = Array(v) }
|
73
|
+
|
74
|
+
doc = @context.storage.get_trackers
|
75
|
+
|
76
|
+
doc['trackers'][tracker_id] =
|
77
|
+
{ 'wfid' => wfid,
|
78
|
+
'action' => action,
|
79
|
+
'id' => tracker_id,
|
80
|
+
'conditions' => conditions,
|
81
|
+
'msg' => msg }
|
82
|
+
|
83
|
+
r = @context.storage.put(doc)
|
84
|
+
|
85
|
+
add_tracker(wfid, action, tracker_id, conditions, msg) if r
|
86
|
+
# the put failed, have to redo the work
|
87
|
+
|
88
|
+
tracker_id
|
89
|
+
end
|
90
|
+
|
91
|
+
# Removes a tracker (usually when a 'listen' expression replies to its
|
92
|
+
# parent expression or is cancelled).
|
93
|
+
#
|
94
|
+
def remove_tracker(fei_sid_or_id, wfid=nil)
|
95
|
+
|
96
|
+
tracker_id =
|
97
|
+
if fei_sid_or_id.is_a?(String)
|
98
|
+
fei_sid_or_id
|
99
|
+
else
|
100
|
+
Ruote.to_storage_id(fei_sid_or_id)
|
101
|
+
end
|
102
|
+
|
103
|
+
remove([ tracker_id ], wfid)
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
|
108
|
+
# Removes a set of tracker ids and updated the tracker document.
|
109
|
+
#
|
110
|
+
def remove(tracker_ids, wfid)
|
111
|
+
|
112
|
+
return if tracker_ids.empty?
|
113
|
+
|
114
|
+
doc ||= @context.storage.get_trackers(wfid)
|
115
|
+
|
116
|
+
return if (doc['trackers'].keys & tracker_ids).empty?
|
117
|
+
|
118
|
+
doc['wfid'] = wfid
|
119
|
+
# a little helper for some some storage implementations like ruote-swf
|
120
|
+
# they need to know what workflow execution is targetted.
|
121
|
+
|
122
|
+
tracker_ids.each { |ti| doc['trackers'].delete(ti) }
|
123
|
+
r = @context.storage.put(doc)
|
124
|
+
|
125
|
+
remove(tracker_ids, wfid) if r
|
126
|
+
# the put failed, have to redo the work
|
127
|
+
end
|
128
|
+
|
129
|
+
# The method behind on_pre_msg and on_msg. Filters msgs against trackers.
|
130
|
+
# Triggers trackers if there is a match.
|
131
|
+
#
|
132
|
+
def on_message(pre, message)
|
46
133
|
|
47
|
-
m_error = message['error']
|
48
134
|
m_wfid = message['wfid'] || (message['fei']['wfid'] rescue nil)
|
135
|
+
m_error = message['error']
|
136
|
+
|
49
137
|
m_action = message['action']
|
138
|
+
m_action = "pre_#{m_action}" if pre
|
50
139
|
|
51
140
|
msg = m_action == 'error_intercepted' ? message['msg'] : message
|
52
141
|
|
53
|
-
|
142
|
+
ids_to_remove = []
|
143
|
+
|
144
|
+
trackers.each do |tracker_id, tracker|
|
54
145
|
|
55
146
|
# filter msgs
|
56
147
|
|
@@ -64,79 +155,84 @@ module Ruote
|
|
64
155
|
|
65
156
|
if tracker_id == 'on_error' || tracker_id == 'on_terminate'
|
66
157
|
|
67
|
-
|
158
|
+
fs = msg['workitem']['fields']
|
68
159
|
|
69
|
-
next if m_action == 'error_intercepted' &&
|
70
|
-
next if m_action == 'terminated' && (
|
160
|
+
next if m_action == 'error_intercepted' && fs['__error__']
|
161
|
+
next if m_action == 'terminated' && (fs['__error__'] || fs['__terminate__'])
|
71
162
|
end
|
72
163
|
|
73
|
-
#
|
164
|
+
# remove the message post-trigger?
|
74
165
|
|
75
|
-
|
166
|
+
ids_to_remove << tracker_id if tracker['msg'].delete('_auto_remove')
|
76
167
|
|
77
|
-
|
168
|
+
# OK, have to pull the trigger (or alter the message) then
|
78
169
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
if t_action == 'error_intercepted'
|
85
|
-
m['workitem']['fields']['__error__'] = m_error
|
86
|
-
elsif tracker_id == 'on_error' && m_action == 'error_intercepted'
|
87
|
-
m['workitem']['fields']['__error__'] = m_error
|
88
|
-
elsif tracker_id == 'on_terminate' && m_action == 'terminated'
|
89
|
-
m['workitem']['fields']['__terminate__'] = { 'wfid' => m_wfid }
|
170
|
+
if pre && tracker['msg']['_alter']
|
171
|
+
alter(m_wfid, m_error, m_action, msg, tracker)
|
172
|
+
else
|
173
|
+
trigger(m_wfid, m_error, m_action, msg, tracker)
|
90
174
|
end
|
175
|
+
end
|
91
176
|
|
92
|
-
|
93
|
-
|
94
|
-
m['variables'] = fexp ? fexp.compile_variables : {}
|
95
|
-
end
|
177
|
+
remove(ids_to_remove, nil)
|
178
|
+
end
|
96
179
|
|
97
|
-
|
180
|
+
# Alters the msg, only called in "pre" mode.
|
181
|
+
#
|
182
|
+
def alter(m_wfid, m_error, m_action, msg, tracker)
|
183
|
+
|
184
|
+
case tracker['msg'].delete('_alter')
|
185
|
+
when 'merge' then msg.merge!(tracker['msg'])
|
186
|
+
#else ...
|
98
187
|
end
|
99
188
|
end
|
100
189
|
|
101
|
-
#
|
190
|
+
# Prepares the message that gets placed on the ruote msg queue.
|
102
191
|
#
|
103
|
-
def
|
192
|
+
def trigger(m_wfid, m_error, m_action, msg, tracker)
|
104
193
|
|
105
|
-
|
106
|
-
|
194
|
+
t_action = tracker['action']
|
195
|
+
tracker_id = tracker['id']
|
107
196
|
|
108
|
-
|
197
|
+
m = Ruote.fulldup(tracker['msg'])
|
109
198
|
|
110
|
-
|
111
|
-
{ 'wfid' => wfid,
|
112
|
-
'action' => action,
|
113
|
-
'id' => id,
|
114
|
-
'conditions' => conditions,
|
115
|
-
'msg' => msg }
|
199
|
+
action = m.delete('action')
|
116
200
|
|
117
|
-
|
201
|
+
m['wfid'] = m_wfid if m['wfid'] == 'replace'
|
202
|
+
m['wfid'] ||= @context.wfidgen.generate
|
118
203
|
|
119
|
-
|
120
|
-
# the put failed, have to redo the work
|
121
|
-
end
|
204
|
+
m['workitem'] = msg['workitem'] if m['workitem'] == 'replace'
|
122
205
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
206
|
+
if t_action == 'error_intercepted'
|
207
|
+
m['workitem']['fields']['__error__'] = m_error
|
208
|
+
elsif tracker_id == 'on_error' && m_action == 'error_intercepted'
|
209
|
+
m['workitem']['fields']['__error__'] = m_error
|
210
|
+
elsif tracker_id == 'on_terminate' && m_action == 'terminated'
|
211
|
+
m['workitem']['fields']['__terminate__'] = { 'wfid' => m_wfid }
|
212
|
+
end
|
127
213
|
|
128
|
-
|
214
|
+
if m['variables'] == 'compile'
|
215
|
+
fexp = Ruote::Exp::FlowExpression.fetch(@context, msg['fei'])
|
216
|
+
m['variables'] = fexp ? fexp.compile_variables : {}
|
217
|
+
end
|
129
218
|
|
130
|
-
|
219
|
+
@context.storage.put_msg(action, m)
|
220
|
+
end
|
131
221
|
|
132
|
-
|
222
|
+
# Returns the trackers currently registered.
|
223
|
+
#
|
224
|
+
# Note: this is called from on_pre_msg and on_msg, hence two times
|
225
|
+
# for a single msg. We trust the storage implementation to cache it
|
226
|
+
# for us.
|
227
|
+
#
|
228
|
+
def trackers
|
133
229
|
|
134
|
-
|
135
|
-
# the put failed, have to redo the work
|
230
|
+
@context.storage.get_trackers['trackers']
|
136
231
|
end
|
137
232
|
|
138
|
-
|
139
|
-
|
233
|
+
# Given a msg and a hash of conditions, returns true if the msg
|
234
|
+
# matches the conditions.
|
235
|
+
#
|
140
236
|
def does_match?(msg, conditions)
|
141
237
|
|
142
238
|
return true unless conditions
|
@@ -151,12 +247,14 @@ module Ruote
|
|
151
247
|
vv = Ruote.regex_or_s(vv)
|
152
248
|
|
153
249
|
val = case k
|
250
|
+
|
154
251
|
when 'class' then msg['error']['class']
|
155
252
|
when 'message' then msg['error']['message']
|
156
|
-
|
253
|
+
|
254
|
+
else Ruote.lookup(msg, k)
|
157
255
|
end
|
158
256
|
|
159
|
-
val && (vv.is_a?(
|
257
|
+
val && (vv.is_a?(Regexp) ? vv.match(val) : vv == val)
|
160
258
|
end
|
161
259
|
end
|
162
260
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
data/lib/ruote/tree_dot.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
data/lib/ruote/util/deep.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -111,6 +111,7 @@ module Ruote
|
|
111
111
|
# ensure that all keys are strings
|
112
112
|
|
113
113
|
unless k.is_a?(String)
|
114
|
+
|
114
115
|
coll.delete(k)
|
115
116
|
k = k.to_s
|
116
117
|
coll[k] = v
|
@@ -125,8 +126,9 @@ module Ruote
|
|
125
126
|
else
|
126
127
|
block.call(coll, k, v)
|
127
128
|
end
|
129
|
+
end
|
128
130
|
|
129
|
-
|
131
|
+
if v.is_a?(Array) || v.is_a?(Hash)
|
130
132
|
|
131
133
|
deep_mutate(v, keys, coll, &block)
|
132
134
|
end
|
data/lib/ruote/util/filter.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
data/lib/ruote/util/hashdot.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
data/lib/ruote/util/look.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
data/lib/ruote/util/lookup.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
data/lib/ruote/util/misc.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2005-
|
2
|
+
# Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -200,5 +200,55 @@ module Ruote
|
|
200
200
|
|
201
201
|
o.is_a?(Array) ? o : o.to_s.split(/\s*,\s*/).collect { |e| e.strip }
|
202
202
|
end
|
203
|
+
|
204
|
+
# A bit like #inspect but produces a tighter output (ambiguous to machines).
|
205
|
+
#
|
206
|
+
def self.insp(o, opts={})
|
207
|
+
|
208
|
+
case o
|
209
|
+
when nil
|
210
|
+
'nil'
|
211
|
+
when Hash
|
212
|
+
trim = opts[:trim] || []
|
213
|
+
'{' +
|
214
|
+
o.reject { |k, v|
|
215
|
+
v.nil? && trim.include?(k.to_s)
|
216
|
+
}.collect { |k, v|
|
217
|
+
"#{k}: #{insp(v)}"
|
218
|
+
}.join(', ') +
|
219
|
+
'}'
|
220
|
+
when Array
|
221
|
+
'[' + o.collect { |e| insp(e) }.join(', ') + ']'
|
222
|
+
when String
|
223
|
+
o.match(/\s/) ? o.inspect : o
|
224
|
+
else
|
225
|
+
o.inspect
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def self.pps(o, w=79)
|
230
|
+
|
231
|
+
PP.pp(o, StringIO.new, w).string
|
232
|
+
end
|
233
|
+
|
234
|
+
#--
|
235
|
+
# [de]camelize
|
236
|
+
#++
|
237
|
+
|
238
|
+
# Our own quick camelize implementation (no need to require active support).
|
239
|
+
#
|
240
|
+
def self.camelize(s, first_up=false)
|
241
|
+
|
242
|
+
s = s.capitalize if first_up
|
243
|
+
|
244
|
+
s.gsub(/(_.)/) { |x| x[1, 1].upcase }
|
245
|
+
end
|
246
|
+
|
247
|
+
# Quick decamelize implementation.
|
248
|
+
#
|
249
|
+
def self.decamelize(s)
|
250
|
+
|
251
|
+
s.gsub(/(.)([A-Z])/, '\1_\2').downcase
|
252
|
+
end
|
203
253
|
end
|
204
254
|
|