Skip to content

Commit 4d96326

Browse files
committed
Extract SelectInput and CheckboxInput
Both are subclasses of `ArrayInput`. Now, `ArrayInput#fill` chains together successive calls to `SelectInput#fill` and `CheckboxInput#fill`, finally failing with an informative exception if neither inputs exist on the page.
1 parent 27ac0d0 commit 4d96326

File tree

4 files changed

+91
-33
lines changed

4 files changed

+91
-33
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ around `I18n.t`.
150150
| `Date`, `ActiveSupport::TimeWithZone` | `select` year, month, and day |
151151
| `TrueClass` | `check` |
152152
| `FalseClass` | `uncheck` |
153-
| `Array` | `check` or `select` each array member, which should all be strings |
153+
| `Array` | `check` or `select` each array member, which should all be strings. If not all items can be selected or checked, an error will be thrown.|
154154
| `File` | `attach_file` with `File#path` |
155155

156156
* Formulaic is currently tied to `simple_form` translations and field structure.

lib/formulaic/inputs/array_input.rb

+17-32
Original file line numberDiff line numberDiff line change
@@ -7,49 +7,34 @@ def initialize(label, value)
77
end
88

99
def fill
10-
if has_select?
11-
select_options
12-
elsif has_check_boxes?
13-
check_boxes
14-
else
15-
raise InputNotFound.new(%[Unable to find checkboxes or select[multiple] "#{label}" containing all options #{value.inspect}.])
16-
end
10+
attempt_to_fill_selects ||
11+
attempt_to_fill_checkboxes ||
12+
raise_input_error
1713
end
1814

1915
private
2016

21-
def has_select?
22-
has_field?(label, type: "select") &&
23-
begin
24-
select = find_field(label, type: "select")
25-
select[:multiple].present? &&
26-
contains_all_options?(select.all("option"))
27-
end
17+
def attempt_to_fill_selects
18+
SelectInput.new(label, value).fill
2819
end
2920

30-
def has_check_boxes?
31-
checkbox_name_selector =
32-
"input[type='checkbox']" \
33-
"[name='#{label.model_name}[#{label.attribute}][]']"
34-
check_box_labels =
35-
all(
36-
"#{checkbox_name_selector} ~ label," \
37-
"label:has(#{checkbox_name_selector})"
38-
).to_a.flatten
39-
contains_all_options?(check_box_labels)
40-
end
41-
42-
def select_options
43-
value.each { |option| select option, from: label.to_str }
44-
end
45-
46-
def check_boxes
47-
value.each { |checkbox| check checkbox }
21+
def attempt_to_fill_checkboxes
22+
CheckboxInput.new(label, value).fill
4823
end
4924

5025
def contains_all_options?(nodes)
5126
nodes.map(&:text).to_set.superset?(value.to_set)
5227
end
28+
29+
def raise_input_error
30+
raise(
31+
InputNotFound,
32+
%[Unable to find checkboxes or select[multiple] "#{label}" containing all options #{value.inspect}.]
33+
)
34+
end
5335
end
5436
end
5537
end
38+
39+
require 'formulaic/inputs/checkbox_input'
40+
require 'formulaic/inputs/select_input'
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module Formulaic
2+
module Inputs
3+
class CheckboxInput < ArrayInput
4+
def fill
5+
if has_check_boxes?
6+
check_boxes
7+
true
8+
else
9+
false
10+
end
11+
end
12+
13+
private
14+
15+
def has_check_boxes?
16+
contains_all_options?(checkbox_labels)
17+
end
18+
19+
def check_boxes
20+
value.each { |checkbox| check checkbox }
21+
end
22+
23+
def checkbox_labels
24+
all(
25+
"#{checkbox_name_selector} ~ label," \
26+
"label:has(#{checkbox_name_selector})"
27+
)
28+
end
29+
30+
def checkbox_name_selector
31+
"input[type='checkbox']" \
32+
"[name='#{label.model_name}[#{label.attribute}][]']"
33+
end
34+
end
35+
end
36+
end

lib/formulaic/inputs/select_input.rb

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module Formulaic
2+
module Inputs
3+
class SelectInput < ArrayInput
4+
def fill
5+
if has_multiple_select?
6+
select_options
7+
true
8+
else
9+
false
10+
end
11+
end
12+
13+
private
14+
15+
def select_options
16+
value.each { |option| select option, from: label.to_str }
17+
end
18+
19+
def has_multiple_select?
20+
has_select? && select_is_multiple?
21+
end
22+
23+
def has_select?
24+
has_field?(label, type: "select")
25+
end
26+
27+
def select_is_multiple?
28+
select_element[:multiple].present? &&
29+
contains_all_options?(select_element.all("option"))
30+
end
31+
32+
def select_element
33+
@select_element ||= find_field(label, type: "select")
34+
end
35+
end
36+
end
37+
end

0 commit comments

Comments
 (0)