simple_form_with_client_validation 0.0.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.md +6 -0
- data/MIT-LICENSE +20 -0
- data/README.md +783 -0
- data/lib/generators/simple_form_with_client_validation/USAGE +3 -0
- data/lib/generators/simple_form_with_client_validation/install_generator.rb +32 -0
- data/lib/generators/simple_form_with_client_validation/templates/README +12 -0
- data/lib/generators/simple_form_with_client_validation/templates/_form.html.erb +13 -0
- data/lib/generators/simple_form_with_client_validation/templates/_form.html.haml +10 -0
- data/lib/generators/simple_form_with_client_validation/templates/_form.html.slim +10 -0
- data/lib/generators/simple_form_with_client_validation/templates/config/initializers/simple_form.rb.tt +179 -0
- data/lib/generators/simple_form_with_client_validation/templates/config/locales/simple_form.en.yml +26 -0
- data/lib/simple_form_with_client_validation/action_view_extensions/builder.rb +331 -0
- data/lib/simple_form_with_client_validation/action_view_extensions/form_helper.rb +74 -0
- data/lib/simple_form_with_client_validation/components/errors.rb +35 -0
- data/lib/simple_form_with_client_validation/components/hints.rb +18 -0
- data/lib/simple_form_with_client_validation/components/html5.rb +26 -0
- data/lib/simple_form_with_client_validation/components/label_input.rb +15 -0
- data/lib/simple_form_with_client_validation/components/labels.rb +79 -0
- data/lib/simple_form_with_client_validation/components/maxlength.rb +41 -0
- data/lib/simple_form_with_client_validation/components/min_max.rb +50 -0
- data/lib/simple_form_with_client_validation/components/minlength.rb +41 -0
- data/lib/simple_form_with_client_validation/components/pattern.rb +34 -0
- data/lib/simple_form_with_client_validation/components/placeholders.rb +16 -0
- data/lib/simple_form_with_client_validation/components/readonly.rb +22 -0
- data/lib/simple_form_with_client_validation/components.rb +21 -0
- data/lib/simple_form_with_client_validation/core_ext/hash.rb +16 -0
- data/lib/simple_form_with_client_validation/error_notification.rb +48 -0
- data/lib/simple_form_with_client_validation/form_builder.rb +484 -0
- data/lib/simple_form_with_client_validation/helpers/autofocus.rb +11 -0
- data/lib/simple_form_with_client_validation/helpers/disabled.rb +15 -0
- data/lib/simple_form_with_client_validation/helpers/readonly.rb +15 -0
- data/lib/simple_form_with_client_validation/helpers/required.rb +35 -0
- data/lib/simple_form_with_client_validation/helpers/validators.rb +44 -0
- data/lib/simple_form_with_client_validation/helpers.rb +12 -0
- data/lib/simple_form_with_client_validation/i18n_cache.rb +22 -0
- data/lib/simple_form_with_client_validation/inputs/base.rb +162 -0
- data/lib/simple_form_with_client_validation/inputs/block_input.rb +14 -0
- data/lib/simple_form_with_client_validation/inputs/boolean_input.rb +64 -0
- data/lib/simple_form_with_client_validation/inputs/collection_check_boxes_input.rb +21 -0
- data/lib/simple_form_with_client_validation/inputs/collection_input.rb +101 -0
- data/lib/simple_form_with_client_validation/inputs/collection_radio_buttons_input.rb +63 -0
- data/lib/simple_form_with_client_validation/inputs/collection_select_input.rb +14 -0
- data/lib/simple_form_with_client_validation/inputs/date_time_input.rb +28 -0
- data/lib/simple_form_with_client_validation/inputs/file_input.rb +9 -0
- data/lib/simple_form_with_client_validation/inputs/grouped_collection_select_input.rb +41 -0
- data/lib/simple_form_with_client_validation/inputs/hidden_input.rb +17 -0
- data/lib/simple_form_with_client_validation/inputs/numeric_input.rb +24 -0
- data/lib/simple_form_with_client_validation/inputs/password_input.rb +12 -0
- data/lib/simple_form_with_client_validation/inputs/priority_input.rb +24 -0
- data/lib/simple_form_with_client_validation/inputs/range_input.rb +14 -0
- data/lib/simple_form_with_client_validation/inputs/string_input.rb +23 -0
- data/lib/simple_form_with_client_validation/inputs/text_input.rb +11 -0
- data/lib/simple_form_with_client_validation/inputs.rb +21 -0
- data/lib/simple_form_with_client_validation/map_type.rb +16 -0
- data/lib/simple_form_with_client_validation/version.rb +3 -0
- data/lib/simple_form_with_client_validation/wrappers/builder.rb +115 -0
- data/lib/simple_form_with_client_validation/wrappers/many.rb +78 -0
- data/lib/simple_form_with_client_validation/wrappers/root.rb +34 -0
- data/lib/simple_form_with_client_validation/wrappers/single.rb +18 -0
- data/lib/simple_form_with_client_validation/wrappers.rb +8 -0
- data/lib/simple_form_with_client_validation.rb +218 -0
- data/test/action_view_extensions/builder_test.rb +577 -0
- data/test/action_view_extensions/form_helper_test.rb +104 -0
- data/test/components/label_test.rb +310 -0
- data/test/form_builder/association_test.rb +177 -0
- data/test/form_builder/button_test.rb +47 -0
- data/test/form_builder/error_notification_test.rb +79 -0
- data/test/form_builder/error_test.rb +121 -0
- data/test/form_builder/general_test.rb +356 -0
- data/test/form_builder/hint_test.rb +139 -0
- data/test/form_builder/input_field_test.rb +63 -0
- data/test/form_builder/label_test.rb +71 -0
- data/test/form_builder/wrapper_test.rb +149 -0
- data/test/generators/simple_form_generator_test.rb +32 -0
- data/test/inputs/boolean_input_test.rb +108 -0
- data/test/inputs/collection_check_boxes_input_test.rb +224 -0
- data/test/inputs/collection_radio_buttons_input_test.rb +326 -0
- data/test/inputs/collection_select_input_test.rb +241 -0
- data/test/inputs/datetime_input_test.rb +99 -0
- data/test/inputs/disabled_test.rb +38 -0
- data/test/inputs/discovery_test.rb +61 -0
- data/test/inputs/file_input_test.rb +16 -0
- data/test/inputs/general_test.rb +69 -0
- data/test/inputs/grouped_collection_select_input_test.rb +118 -0
- data/test/inputs/hidden_input_test.rb +30 -0
- data/test/inputs/numeric_input_test.rb +173 -0
- data/test/inputs/priority_input_test.rb +43 -0
- data/test/inputs/readonly_test.rb +61 -0
- data/test/inputs/required_test.rb +113 -0
- data/test/inputs/string_input_test.rb +140 -0
- data/test/inputs/text_input_test.rb +29 -0
- data/test/simple_form_test.rb +9 -0
- data/test/support/discovery_inputs.rb +21 -0
- data/test/support/misc_helpers.rb +102 -0
- data/test/support/mock_controller.rb +24 -0
- data/test/support/mock_response.rb +14 -0
- data/test/support/models.rb +210 -0
- data/test/test_helper.rb +95 -0
- metadata +227 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Inputs
|
3
|
+
class CollectionRadioButtonsInput < CollectionInput
|
4
|
+
def input
|
5
|
+
label_method, value_method = detect_collection_methods
|
6
|
+
|
7
|
+
@builder.send("collection_#{input_type}",
|
8
|
+
attribute_name, collection, value_method, label_method,
|
9
|
+
input_options, input_html_options, &collection_block_for_nested_boolean_style
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
def input_options
|
14
|
+
options = super
|
15
|
+
apply_default_collection_options!(options)
|
16
|
+
apply_nested_boolean_collection_options!(options) if nested_boolean_style?
|
17
|
+
options
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def apply_default_collection_options!(options)
|
23
|
+
options[:item_wrapper_tag] ||= options.fetch(:item_wrapper_tag, SimpleFormWithClientValidation.item_wrapper_tag)
|
24
|
+
options[:item_wrapper_class] = [
|
25
|
+
item_wrapper_class, options[:item_wrapper_class], SimpleFormWithClientValidation.item_wrapper_class
|
26
|
+
].compact.presence
|
27
|
+
|
28
|
+
options[:collection_wrapper_tag] ||= options.fetch(:collection_wrapper_tag, SimpleFormWithClientValidation.collection_wrapper_tag)
|
29
|
+
options[:collection_wrapper_class] = [
|
30
|
+
options[:collection_wrapper_class], SimpleFormWithClientValidation.collection_wrapper_class
|
31
|
+
].compact.presence
|
32
|
+
end
|
33
|
+
|
34
|
+
# Force item wrapper to be a label when using nested boolean, to support
|
35
|
+
# configuring classes through :item_wrapper_class, and to maintain
|
36
|
+
# compatibility with :inline style and default :item_wrapper_tag.
|
37
|
+
def apply_nested_boolean_collection_options!(options)
|
38
|
+
options[:item_wrapper_tag] = :label
|
39
|
+
end
|
40
|
+
|
41
|
+
def collection_block_for_nested_boolean_style
|
42
|
+
return unless nested_boolean_style?
|
43
|
+
|
44
|
+
proc { |builder| build_nested_boolean_style_item_tag(builder) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def build_nested_boolean_style_item_tag(collection_builder)
|
48
|
+
collection_builder.radio_button + collection_builder.text
|
49
|
+
end
|
50
|
+
|
51
|
+
def item_wrapper_class
|
52
|
+
"radio"
|
53
|
+
end
|
54
|
+
|
55
|
+
# Do not attempt to generate label[for] attributes by default, unless an
|
56
|
+
# explicit html option is given. This avoids generating labels pointing to
|
57
|
+
# non existent fields.
|
58
|
+
def generate_label_for_attribute?
|
59
|
+
false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Inputs
|
3
|
+
class CollectionSelectInput < CollectionInput
|
4
|
+
def input
|
5
|
+
label_method, value_method = detect_collection_methods
|
6
|
+
|
7
|
+
@builder.collection_select(
|
8
|
+
attribute_name, collection, value_method, label_method,
|
9
|
+
input_options, input_html_options
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Inputs
|
3
|
+
class DateTimeInput < Base
|
4
|
+
def input
|
5
|
+
@builder.send(:"#{input_type}_select", attribute_name, input_options, input_html_options)
|
6
|
+
end
|
7
|
+
|
8
|
+
def has_required?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def label_target
|
15
|
+
position = case input_type
|
16
|
+
when :date, :datetime
|
17
|
+
date_order = input_options[:order] || I18n.t('date.order')
|
18
|
+
date_order.first
|
19
|
+
else
|
20
|
+
:hour
|
21
|
+
end
|
22
|
+
|
23
|
+
position = ActionView::Helpers::DateTimeSelector::POSITION[position]
|
24
|
+
"#{attribute_name}_#{position}i"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Inputs
|
3
|
+
class GroupedCollectionSelectInput < CollectionInput
|
4
|
+
def input
|
5
|
+
label_method, value_method = detect_collection_methods
|
6
|
+
@builder.grouped_collection_select(attribute_name, grouped_collection,
|
7
|
+
group_method, group_label_method, value_method, label_method,
|
8
|
+
input_options, input_html_options)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def grouped_collection
|
14
|
+
@grouped_collection ||= begin
|
15
|
+
grouped_collection = options.delete(:collection)
|
16
|
+
grouped_collection.respond_to?(:call) ? grouped_collection.call : grouped_collection.to_a
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Sample collection
|
21
|
+
def collection
|
22
|
+
@collection ||= grouped_collection.first.try(:send, group_method) || []
|
23
|
+
end
|
24
|
+
|
25
|
+
def group_method
|
26
|
+
@group_method ||= options.delete(:group_method)
|
27
|
+
end
|
28
|
+
|
29
|
+
def group_label_method
|
30
|
+
label = options.delete(:group_label_method)
|
31
|
+
|
32
|
+
unless label
|
33
|
+
common_method_for = detect_common_display_methods(detect_collection_classes(grouped_collection))
|
34
|
+
label = common_method_for[:label]
|
35
|
+
end
|
36
|
+
|
37
|
+
label
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Inputs
|
3
|
+
class HiddenInput < Base
|
4
|
+
disable :label, :errors, :hint, :required
|
5
|
+
|
6
|
+
def input
|
7
|
+
@builder.hidden_field(attribute_name, input_html_options)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def required_class
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Inputs
|
3
|
+
class NumericInput < Base
|
4
|
+
enable :placeholder, :min_max
|
5
|
+
|
6
|
+
def input
|
7
|
+
add_size!
|
8
|
+
input_html_classes.unshift("numeric")
|
9
|
+
if html5?
|
10
|
+
input_html_options[:type] ||= "number"
|
11
|
+
input_html_options[:step] ||= integer? ? 1 : "any"
|
12
|
+
end
|
13
|
+
@builder.text_field(attribute_name, input_html_options)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Rails adds the size attr by default, if the :size key does not exist.
|
19
|
+
def add_size!
|
20
|
+
input_html_options[:size] ||= nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Inputs
|
3
|
+
class PriorityInput < CollectionSelectInput
|
4
|
+
def input
|
5
|
+
@builder.send(:"#{input_type}_select", attribute_name, input_priority,
|
6
|
+
input_options, input_html_options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def input_priority
|
10
|
+
options[:priority] || SimpleFormWithClientValidation.send(:"#{input_type}_priority")
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def has_required?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def skip_include_blank?
|
20
|
+
super || input_priority.present?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Inputs
|
3
|
+
class StringInput < Base
|
4
|
+
enable :placeholder, :maxlength, :pattern
|
5
|
+
|
6
|
+
def input
|
7
|
+
unless string?
|
8
|
+
input_html_classes.unshift("string")
|
9
|
+
input_html_options[:type] ||= input_type if html5?
|
10
|
+
end
|
11
|
+
|
12
|
+
add_size!
|
13
|
+
@builder.text_field(attribute_name, input_html_options)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def string?
|
19
|
+
input_type == :string
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Inputs
|
3
|
+
autoload :Base, 'simple_form_with_client_validation/inputs/base'
|
4
|
+
autoload :BlockInput, 'simple_form_with_client_validation/inputs/block_input'
|
5
|
+
autoload :BooleanInput, 'simple_form_with_client_validation/inputs/boolean_input'
|
6
|
+
autoload :CollectionCheckBoxesInput, 'simple_form_with_client_validation/inputs/collection_check_boxes_input'
|
7
|
+
autoload :CollectionInput, 'simple_form_with_client_validation/inputs/collection_input'
|
8
|
+
autoload :CollectionRadioButtonsInput, 'simple_form_with_client_validation/inputs/collection_radio_buttons_input'
|
9
|
+
autoload :CollectionSelectInput, 'simple_form_with_client_validation/inputs/collection_select_input'
|
10
|
+
autoload :DateTimeInput, 'simple_form_with_client_validation/inputs/date_time_input'
|
11
|
+
autoload :FileInput, 'simple_form_with_client_validation/inputs/file_input'
|
12
|
+
autoload :GroupedCollectionSelectInput, 'simple_form_with_client_validation/inputs/grouped_collection_select_input'
|
13
|
+
autoload :HiddenInput, 'simple_form_with_client_validation/inputs/hidden_input'
|
14
|
+
autoload :NumericInput, 'simple_form_with_client_validation/inputs/numeric_input'
|
15
|
+
autoload :PasswordInput, 'simple_form_with_client_validation/inputs/password_input'
|
16
|
+
autoload :PriorityInput, 'simple_form_with_client_validation/inputs/priority_input'
|
17
|
+
autoload :RangeInput, 'simple_form_with_client_validation/inputs/range_input'
|
18
|
+
autoload :StringInput, 'simple_form_with_client_validation/inputs/string_input'
|
19
|
+
autoload :TextInput, 'simple_form_with_client_validation/inputs/text_input'
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
2
|
+
|
3
|
+
module SimpleFormWithClientValidation
|
4
|
+
module MapType
|
5
|
+
def self.extended(base)
|
6
|
+
base.class_attribute :mappings
|
7
|
+
base.mappings = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def map_type(*types)
|
11
|
+
map_to = types.extract_options![:to]
|
12
|
+
raise ArgumentError, "You need to give :to as option to map_type" unless map_to
|
13
|
+
self.mappings = mappings.merge types.each_with_object({}) { |t, m| m[t] = map_to }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module SimpleFormWithClientValidation
|
2
|
+
module Wrappers
|
3
|
+
# Provides the builder syntax for components. The builder provides
|
4
|
+
# three methods `use`, `optional` and `wrapper` and they allow the following invocations:
|
5
|
+
#
|
6
|
+
# config.wrappers do |b|
|
7
|
+
# # Use a single component
|
8
|
+
# b.use :html5
|
9
|
+
#
|
10
|
+
# # Use the component, but do not automatically lookup. It will only be triggered when
|
11
|
+
# # :placeholder is explicitly set.
|
12
|
+
# b.optional :placeholder
|
13
|
+
#
|
14
|
+
# # Use a component with specific wrapper options
|
15
|
+
# b.use :error, :wrap_with => { :tag => "span", :class => "error" }
|
16
|
+
#
|
17
|
+
# # Use a set of components by wrapping them in a tag+class.
|
18
|
+
# b.wrapper :tag => "div", :class => "another" do |ba|
|
19
|
+
# ba.use :label
|
20
|
+
# ba.use :input
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # Use a set of components by wrapping them in a tag+class.
|
24
|
+
# # This wrapper is identified by :label_input, which means it can
|
25
|
+
# # be turned off on demand with `f.input :name, :label_input => false`
|
26
|
+
# b.wrapper :label_input, :tag => "div", :class => "another" do |ba|
|
27
|
+
# ba.use :label
|
28
|
+
# ba.use :input
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# The builder also accepts default options at the root level. This is usually
|
33
|
+
# used if you want a component to be disabled by default:
|
34
|
+
#
|
35
|
+
# config.wrappers :hint => false do |b|
|
36
|
+
# b.use :hint
|
37
|
+
# b.use :label_input
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# In the example above, hint defaults to false, which means it won't automatically
|
41
|
+
# do the lookup anymore. It will only be triggered when :hint is explicitly set.
|
42
|
+
class Builder
|
43
|
+
def initialize(options)
|
44
|
+
@options = options
|
45
|
+
@components = []
|
46
|
+
end
|
47
|
+
|
48
|
+
#this triggers the use of this option
|
49
|
+
def use(name, options=nil, &block)
|
50
|
+
if block_given?
|
51
|
+
ActiveSupport::Deprecation.warn "Passing a block to use is deprecated. " \
|
52
|
+
"Please use wrapper instead of use."
|
53
|
+
return wrapper(name, options, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
if options && options.keys != [:wrap_with]
|
57
|
+
ActiveSupport::Deprecation.warn "Passing :tag, :class and others to use is deprecated. " \
|
58
|
+
"Please invoke b.use #{name.inspect}, :wrap_with => #{options.inspect} instead."
|
59
|
+
options = { :wrap_with => options }
|
60
|
+
end
|
61
|
+
|
62
|
+
if options && wrapper = options[:wrap_with]
|
63
|
+
@components << Single.new(name, wrapper)
|
64
|
+
else
|
65
|
+
@components << name
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def optional(name, options=nil, &block)
|
70
|
+
if block_given?
|
71
|
+
ActiveSupport::Deprecation.warn "Passing a block to optional is deprecated. " \
|
72
|
+
"Please use wrapper instead of optional."
|
73
|
+
return wrapper(name, options, &block)
|
74
|
+
end
|
75
|
+
|
76
|
+
if options && options.keys != [:wrap_with]
|
77
|
+
ActiveSupport::Deprecation.warn "Passing :tag, :class and others to optional is deprecated. " \
|
78
|
+
"Please invoke b.optional #{name.inspect}, :wrap_with => #{options.inspect} instead."
|
79
|
+
options = { :wrap_with => options }
|
80
|
+
end
|
81
|
+
|
82
|
+
@options[name] = false
|
83
|
+
use(name, options, &block)
|
84
|
+
end
|
85
|
+
|
86
|
+
def wrapper(name, options=nil)
|
87
|
+
if block_given?
|
88
|
+
#setting name to nil if only a hash passed in
|
89
|
+
name, options = nil, name if name.is_a?(Hash)
|
90
|
+
|
91
|
+
#create a builder based on current options of parent
|
92
|
+
builder = self.class.new(@options)
|
93
|
+
|
94
|
+
|
95
|
+
options ||= {}
|
96
|
+
#use div if nothing else supplied
|
97
|
+
options[:tag] = :div if options[:tag].nil?
|
98
|
+
|
99
|
+
#now run the block setup stuff (use, optional, and wrappers)
|
100
|
+
yield builder
|
101
|
+
|
102
|
+
#turn this builder into a Many object (wrapper for multiple @components) and
|
103
|
+
#add to parent @components
|
104
|
+
@components << Many.new(name, builder.to_a, options)
|
105
|
+
else
|
106
|
+
raise ArgumentError, "A block is required as argument to wrapper"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def to_a
|
111
|
+
@components
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|