webflow 0.0.1

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.
@@ -0,0 +1,312 @@
1
+ #--
2
+ # Copyright (c) 2007 The World in General
3
+ #
4
+ # Released under the Creative Commons Attribution-Share Alike 3.0 License.
5
+ # Licence details available at : http://creativecommons.org/licenses/by-sa/3.0/
6
+ #
7
+ # Created by Luc Boudreau ( lucboudreau at gmail )
8
+ #
9
+ # The above copyright notice and this permission notice shall be
10
+ # included in all copies or substantial portions of the Software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+ #++
20
+
21
+ # This module adds helper methods to WebFlow controllers. See each method
22
+ # for a complete description of their function.
23
+
24
+ require "webflow/base"
25
+
26
+ module WebFlow
27
+ module BaseHelper
28
+
29
+
30
+ # Creates a submit button to send the parent form to an WebFlow controller.
31
+ # The options array takes the same values as the standard Rails submit_tag.
32
+ #def flow_submit_tag(value="Submit", event_name='', options={})
33
+ #
34
+ # # Convert keys to strings
35
+ # options.stringify_keys!
36
+ #
37
+ # # We can't use the disable_with option since disabling the button will
38
+ # # prevent some browsers from sending the submit button name along
39
+ # # with the form data. We need this button to send the event name.
40
+ # options.delete("disable_with")
41
+ #
42
+ # # Generate the tag
43
+ # tag :input, {"type" => "submit",
44
+ # "name" => "#{WebFlow::Base.event_input_name_prefix}#{WebFlow::Base.event_prefix}#{event_name}",
45
+ # "value" => value}.update(options.stringify_keys)
46
+ #
47
+ #end
48
+
49
+
50
+ # Creates a link to send an event to an WebFlow controller.
51
+ # The method takes all the standard Rails link_to parameters
52
+ # but needs one more : the event name to return.
53
+ #def flow_link_to(name, event_name='', options = {}, html_options = nil, *parameters_for_method_reference)
54
+ #
55
+ # # Delete the action and controller definition
56
+ # options.delete :action
57
+ # options.delete :controller
58
+ #
59
+ # # Specify the 'index' action
60
+ # options[:action] = :index
61
+ #
62
+ # # Add the flow key to the url
63
+ # options[WebFlow::Base.flow_execution_key_id] = @flow_id
64
+ #
65
+ # # Add the event name
66
+ # options[WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event_name.to_s] = WebFlow::Base.event_prefix + event_name.to_s
67
+ #
68
+ # # Call the standard link_to helper
69
+ # link_to name, options, html_options, *parameters_for_method_reference
70
+ #
71
+ #end
72
+
73
+
74
+ # Creates a form tag to send data to the WebFlow controller.
75
+ # Takes the same parameters as Rail's form_tag, but adds the flow
76
+ # exec key hidden input. You can either declare it as a returning
77
+ # function :
78
+ #
79
+ # <%= flow_form_tag %>
80
+ #
81
+ # or give it a block :
82
+ #
83
+ # <% flow_form_tag do |form| %>
84
+ #
85
+ # See end_flow_form_tag to close the first use case.
86
+ #def flow_form_tag(options={}, &block)
87
+ #
88
+ # # Init the HTML subhash if required
89
+ # options[:html] ||= {}
90
+ #
91
+ # # Remove the action html parameter
92
+ # options[:html].delete(:action)
93
+ #
94
+ # # There are two use cases.
95
+ # #
96
+ # # 1. The user has passed a block
97
+ # # We have to extend the block to add our controls
98
+ # #
99
+ # # 2. The user hasn't passed a block
100
+ # # We add our inputs at the end of the returned string
101
+ # #
102
+ # if block_given?
103
+ #
104
+ # # Okay, here's the strategy. We create a 'file' variable which calls all
105
+ # # necessary methods. Then, we tell Rails to evaluate all this while binding
106
+ # # the correct Ruby context to the new block.
107
+ # # Thanks a million to Guy Nador at http://devblog.famundo.com/articles/2007/03/28/lost-in-binding-adventures-in-ruby-metaprogramming
108
+ # # for this hack.
109
+ #
110
+ # @res = <<-EOF
111
+ #
112
+ # #{form_tag(url_for(:action => 'index'), options[:html])}
113
+ #
114
+ #
115
+ # #{capture(&block)}
116
+ #
117
+ #
118
+ # #{tag('input', {:type => :hidden, :name => WebFlow::Base.flow_execution_key_id, :value => @flow_id})}
119
+ #
120
+ # #{end_form_tag}
121
+ #
122
+ # EOF
123
+ #
124
+ #
125
+ # # Finally, launch execution.
126
+ # eval '_erbout.concat @res', block
127
+ #
128
+ #
129
+ # else
130
+ #
131
+ # # Looks like the user didn't pass a block, it's more simple like that.
132
+ # # We just concatenate our stuff at the end of the form_tag call
133
+ # result = form_tag(url_for(:action => 'index'), options[:html])
134
+ #
135
+ # # Add the flow key input
136
+ # result << tag('input', {:type => :hidden, :name => WebFlow::Base.flow_execution_key_id, :value => @flow_id})
137
+ #
138
+ # # Add the event input
139
+ # #result << tag( 'input', { :type => :hidden, :name => WebFlow::Base.event_input_name, :id => WebFlow::Base.event_input_name, :value => '' } )
140
+ #
141
+ # return result
142
+ #
143
+ # end
144
+ #
145
+ #
146
+ #end
147
+
148
+
149
+ # Allows the WebFlow framework to use AJAX form submission.
150
+ # Takes all the same parameters as the standard Rails form_remote_tag
151
+ # but alters the options hash to force the 'index' action to be called.
152
+ #def flow_form_remote_tag(options = {}, &block)
153
+ #
154
+ # # I don't know why to do this, they do it in form_remote_tag
155
+ # # and there's no documentation nor comments available... nice going.
156
+ # options[:form] = true
157
+ #
158
+ # # Init the options hash
159
+ # options[:html] ||= {}
160
+ # options[:url] ||= {}
161
+ #
162
+ # # Alter the options to change the destination url so that it points to
163
+ # # the index action
164
+ # options[:url][:action] = :index
165
+ # options[:action] = :index
166
+ #
167
+ # # Alter the onsubmit event to create an ajax form
168
+ # options[:html][:onsubmit] =
169
+ # (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") +
170
+ # "#{remote_function(options)}; return false;"
171
+ #
172
+ # # Call the standard flow_form_tag to do it's job
173
+ # flow_form_tag(options, &block)
174
+ #
175
+ #end
176
+
177
+
178
+ # Helper method to generate a hidden <tt>input</tt> tag for the flow execution key.
179
+ #
180
+ # @returns <tt>input</tt> tag with type hidden
181
+ #
182
+ def flow_key_tag
183
+ hidden_field_tag WebFlow::Base.flow_execution_key_id, @flow_id
184
+ end
185
+
186
+
187
+ def flow_form_tag(url_for_options = {}, options = {}, &block)
188
+ content =
189
+ if block_given?
190
+ form_tag url_for_options, options, &block
191
+ else
192
+ form_tag url_for_options, options
193
+ end
194
+
195
+ content << hidden_field_tag(WebFlow::Base.flow_execution_key_id, @flow_id)
196
+
197
+ content
198
+ end
199
+
200
+
201
+ # Helper method to generate a button element. This is a wrapper method for the Rails button_tag method.
202
+ # It adds a data-remote attribute, if specified, to enable an UJS ajax submission.
203
+ #
204
+ # @param content_or_options
205
+ # @param options
206
+ # @param block
207
+ #
208
+ # @returns <tt>button</tt> tag
209
+ #
210
+ def flow_button_tag(content_or_options = nil, options = nil, &block)
211
+ options = content_or_options if block_given? && content_or_options.is_a?(Hash)
212
+ options ||= {}
213
+ options.stringify_keys!
214
+
215
+ if remote = options.delete("remote")
216
+ options["data-remote"] = remote
217
+ end
218
+
219
+ if event = options.delete("event")
220
+ options["name"] = WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event.to_s
221
+ options["value"] = WebFlow::Base.event_prefix + event.to_s
222
+ end
223
+
224
+ button_tag content_or_options, options, &block
225
+ end
226
+
227
+
228
+ # Helper method to generate an HTML anchor element. This method is a wrapper for the Rails link_to method.
229
+ #
230
+ # @param args options, event_name, html_options
231
+ # @param block optional block
232
+ #
233
+ # @returns <tt>a</tt> tag for submitting flow request
234
+ #
235
+ def flow_link_to(*args, &block)
236
+ if block_given?
237
+ options = args.first || {}
238
+ event_name = args.second
239
+ html_options = args.third
240
+ flow_link_to(capture(&block), event_name, options, html_options)
241
+ else
242
+ name = args[0]
243
+ event_name = args[1]
244
+ options = args[2] || {}
245
+ html_options = args[3]
246
+
247
+ html_options[:method] = 'GET'
248
+ link_to name, append_flow_params(options, event_name), html_options
249
+ end
250
+ end
251
+
252
+ # Alias for Rails standard end_form_tag
253
+ def end_flow_form_tag
254
+ end_form_tag
255
+ end
256
+
257
+ #
258
+ def get_flow_data(key)
259
+ controller.current_flow_user_data[key]
260
+ end
261
+
262
+
263
+ private
264
+
265
+ # Adds required flow params to the generated url
266
+ #
267
+ # @param options Either a Hash, containing appropriate values for creating a url_for, or a String containing a url.
268
+ # @param event_name Name of the flow event to forward the request.
269
+ #
270
+ # @returns options, which can be a Hash or String depending on the passed parameter
271
+ #
272
+ def append_flow_params(options, event_name)
273
+ case options
274
+ when Hash
275
+ options[:url][WebFlow::Base.flow_execution_key_id] = @flow_id
276
+ options[:url][WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event_name.to_s] = WebFlow::Base.event_prefix + event_name.to_s
277
+
278
+ when String
279
+ options << (options.index("?").nil? ? "?" : "&")
280
+ options << "#{WebFlow::Base.flow_execution_key_id}=#{@flow_id}&"
281
+ options << "#{WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event_name.to_s}=#{WebFlow::Base.event_prefix + event_name.to_s}"
282
+ end
283
+
284
+ options
285
+ end
286
+
287
+ # Allows the WebFlow framework to use AJAX form submission.
288
+ # Takes all the same parameters as the standard Rails form_remote_tag, but adds
289
+ # the event name and flow id to the URL to return to the WebFlow controller.
290
+ # The URL is also overridden to point to the 'index' action.
291
+ #def flow_link_to_remote(name, event, options = {}, html_options = {})
292
+ #
293
+ # # Alter the options to change the destination url so that it points to
294
+ # # the index action
295
+ # options[:url] ||= {}
296
+ # options[:url][:action] = :index
297
+ # options[:action] = :index
298
+ #
299
+ # # Add the flow key to the url
300
+ # options[:url][WebFlow::Base.flow_execution_key_id] = @flow_id
301
+ #
302
+ # # Add the event name
303
+ # options[:url][WebFlow::Base.event_input_name_prefix + WebFlow::Base.event_prefix + event.to_s] = WebFlow::Base.event_prefix + event.to_s
304
+ #
305
+ # # Call the standard ajax link creation method
306
+ # link_to_function(name, remote_function(options), html_options)
307
+ #
308
+ #end
309
+
310
+ end
311
+
312
+ end
@@ -0,0 +1,82 @@
1
+ #--
2
+ # Copyright (c) 2007 The World in General
3
+ #
4
+ # Released under the Creative Commons Attribution-Share Alike 3.0 License.
5
+ # Licence details available at : http://creativecommons.org/licenses/by-sa/3.0/
6
+ #
7
+ # Created by Luc Boudreau ( lucboudreau at gmail )
8
+ #
9
+ # The above copyright notice and this permission notice shall be
10
+ # included in all copies or substantial portions of the Software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+ #++
20
+
21
+ module WebFlow
22
+
23
+ # This class is used by steps to return an event descriptor to
24
+ # the WebFlow framework.
25
+ #
26
+ # Use it as :
27
+ #
28
+ # def step_definition
29
+ #
30
+ # (...)
31
+ #
32
+ # WebFlow::Event.new(:success)
33
+ #
34
+ # end
35
+ #
36
+ # There is also a sugar method included in WebFlow::Base which simplifies
37
+ # the event returning process.
38
+ #
39
+ # def step_definition
40
+ #
41
+ # (...)
42
+ #
43
+ # event :success
44
+ #
45
+ # end
46
+ #
47
+ class Event
48
+
49
+ attr_accessor :name
50
+
51
+ # Initializes the class instance
52
+ def initialize(m_event_name)
53
+
54
+ # The name of the event returned
55
+ @name = m_event_name.to_s
56
+
57
+ end
58
+
59
+ end
60
+
61
+ # The SystemEvent class is a subclass of WebFlow::Event and is used
62
+ # internally to trigger plugins execution.
63
+ # Since the plugins are not activated yet, SystemEvents are not used.
64
+ class SystemEvent < WebFlow::Event
65
+
66
+ attr_accessor :controller, :flow_data
67
+
68
+ # Initializes the class instance
69
+ def initialize(m_event_name, m_controller, m_flow_data)
70
+
71
+ # Super controller
72
+ super m_event_name
73
+
74
+ # Set values
75
+ @controller, @flow_data = m_controller, m_flow_data
76
+
77
+ end
78
+
79
+ end
80
+
81
+
82
+ end
@@ -0,0 +1,80 @@
1
+ #--
2
+ # Copyright (c) 2007 The World in General
3
+ #
4
+ # Released under the Creative Commons Attribution-Share Alike 3.0 License.
5
+ # Licence details available at : http://creativecommons.org/licenses/by-sa/3.0/
6
+ #
7
+ # Created by Luc Boudreau ( lucboudreau at gmail )
8
+ #
9
+ # The above copyright notice and this permission notice shall be
10
+ # included in all copies or substantial portions of the Software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+ #++
20
+
21
+
22
+
23
+ module WebFlow
24
+
25
+
26
+
27
+
28
+ # Superclass used to raise errors from within the WebFlow framework.
29
+ class WebFlowError < StandardError
30
+ end
31
+
32
+
33
+
34
+ # Superclass used to raise errors from within the WebFlow framework
35
+ # when no flow corresponding to a given key can be found.
36
+ class NoSuchFlowError < WebFlowError
37
+ end
38
+
39
+
40
+
41
+ # This error class allows plugins to interrupt a flow execution and substitute
42
+ # it's execution result by a given Proc object.
43
+ #
44
+ # Example...
45
+ #
46
+ # my_block = proc { render 'test' }
47
+ # raise( PluginInterruptionError.new( my_block ), "Plugin Interruption..." )
48
+ #
49
+ # In this example, the flow execution chain would be halted and the block
50
+ # passed as a contructor argument would be executed. The Proc code will
51
+ # be executed on the current controller object instance via Ruby's
52
+ # instance_eval mechanism.
53
+ #
54
+ class PluginInterruptionError < WebFlowError
55
+
56
+ # Constructor used to create this error type.
57
+ # Pass a Proc object to be executed upon the rescue
58
+ # of a PluginInterruptionError exception.
59
+ def initialize(&block)
60
+
61
+ @_block = block
62
+
63
+ end
64
+
65
+ # Getter method to obtain the Proc object associated
66
+ # to this PluginInterruptionError instance.
67
+ def block
68
+ @_block
69
+ end
70
+
71
+ private
72
+
73
+ # Declaration of a private constructor to prevent initialization
74
+ # without the block parameter
75
+ def initialize
76
+ end
77
+
78
+ end
79
+
80
+ end