-
-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fallback to select
if array of checkboxes
fail
#34
Conversation
@@ -3,6 +3,8 @@ module Inputs | |||
class ArrayInput < Input | |||
def fill | |||
value.each { |checkbox| check checkbox } | |||
rescue | |||
value.each { |option| select option, from: label } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@calebthompson this is obviously a lazy and naive implementation. I was hoping you'd be able to point me to a more elegant approach if one exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, a little maybe. Check out StringInput for how I've done this before.
ac85b2d
to
149f4eb
Compare
private | ||
|
||
def has_select? | ||
page.has_select?(label) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the docs, it doesn't look like we can filter for <select multiple="true">
Would we really need to check for this? Wouldn't a select
's single/multiple selection come out when trying to fill it in and assert on the side effects of submitting the form?
Also, wouldn't the onus be on the caller to pass in the correct label?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They might, but if we only check for the select, we just change the
selection for each array element then submit - no errors.
I'm a big fan of the Unix philosophy of failing early and loudly.
On Mon, Sep 15, 2014 at 02:26:37PM -0700, Sean Doyle wrote:
@@ -2,6 +2,26 @@ module Formulaic
module Inputs
class ArrayInput < Input
def fill
if has_select?
select_options
else
check_boxes
end
rescue Capybara::ElementNotFound
raise InputNotFound.new(%[Unable to find input "#{label}".])
end
private
def has_select?
page.has_select?(label)
Looking at the docs, it doesn't look like we can filter for multiple selects.
Would we really need to check for this? Wouldn't a
select
's single/multiple selection come out when trying to fill it in and assert on the side effects of submitting the form?Wouldn't the onus be on the caller to pass in the correct label?
Reply to this email directly or view it on GitHub:
https://github.com/thoughtbot/formulaic/pull/34/files#r17569921
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
has_selector? should take attribute selectors: has_selector? "select[multiple]"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When trying to call has_selector?("select[multiple]", label: label)
, the failure reads
invalid keys :label, should be one of :count, :minimum, :maximum, :between, :text, :visible, :exact, :match, :wait
I don't think any of those accepted keys apply to an input's label
I'm not sure how to find the select
with both multiple
and the corresponding label
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, if the select isn't multiple
, we'd just select the last option
provided.
Is correcting this a formulaic concern? Is it a form-filling 'failure'?
I don't think 'silently' failing will be an issue, since controllers expecting an array will be requiring form[field][]
while controllers expecting a single option will require form[field]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally speaking, it's a test's job to show mistakes. The more verbose we can be about that, the more useful Formulaic is.
Consider:
Formulaic::InputNotFound No select or checkbox has all options in [x, y, z].
versus:
ActionController::UnpermittedParameters: found unpermitted parameters: letters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, the former is much more helpful.
However, I don't know how to move forward with this
2e3467d
to
3333da1
Compare
Pushed up ugly but working code. It could benefit from some extract method. |
Your failing test is in a branch at sd-select-array-failing |
Nice work, I'll take a look tomorrow |
end | ||
end | ||
|
||
class SelectInput < ArrayInput |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@calebthompson I know that private classes are more or less a no-no, but I wanted to get your feedback on the extraction before I went any further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might make more sense to have them just be PORO helper classes though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to do that, we'd have to expose label
, value
and somehow share contains_all_options?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
label & value can still be passed in. contains_all_options?
could be moved down into those, but then it'd be duplicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right, I forgot we're passing in label
and value
.
My first instinct was to use SimpleDelegator
, and I passed in self
instead of label, value
. I got to the point where I made those fields public, but then had to duplicate contains_all_options?
, so I fell back to inheritance.
Right, I plan on squashing and authoring a good commit message before this gets merged. |
5d91b18
to
7b3d1cb
Compare
@calebthompson ok squashed my commit and split out the files. What else is blocking this? |
end | ||
end | ||
end | ||
end | ||
|
||
require 'formulaic/inputs/checkbox_input' | ||
require 'formulaic/inputs/select_input' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These need to be at the bottom of the file, since they both depend on ArrayInput
7b3d1cb
to
4d96326
Compare
@@ -26,6 +26,8 @@ def load_translations | |||
awesome: Are you awesome? | |||
bio: Biography | |||
date_of_birth: Date of birth | |||
likes: Likes | |||
dislikes: Dislikes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have / had a passing interest in not having these just be humanized versions of the translations, but that doesn't really matter anymore since we have a lot of those.
LGTM. |
Should these commits get squashed to 1 or are you ok with them as-is? |
Not much of a story being told, I think. Go ahead and squash them. |
420be84
to
4258e08
Compare
* Allows fields that are arrays of strings to be passed to `<select multiple>` inputs * Update README.md * Add coverage for Array of checkboxes * Rescue `Capybara` errors and rethrow as Formulaic * Check for presence of all options in ArrayInput * Raise Formulaic::InputNotFound with useful message if not all options are present in either a select[multiple]'s options or as checkboxes. * Ensure checkboxes exist with `:has` http://dev.w3.org/csswg/selectors4/#relational * 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. * Enure that I18n's aren't humanized
Formulaic now knows how to `select` from a `select[multiple]` if it can't `check` array options as `input[type=checkbox]`. It will also refuse to fill an `Array` value if all elements can't be selected or checked (and they must all be the same action). #34
Allows fields that are arrays of strings to be passed to
<select multiple>
inputs.