Skip to content
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

136 refactor value parser #143

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Conversation

nicoledow
Copy link
Contributor

@nicoledow nicoledow commented Dec 1, 2023

Items Addressed

Address #136 by DRY-ing up the code that checks whether values passed to parsers other than ArrayParser are singular values and raises an error if not.

How It Works

  • Similarly to HashParser, ArrayParser now inherits directly from Base instead of ValueParser (which in turn inherits from Base).
  • ValueParser is now responsible for handling single-value parsers. In its parser method it now raises an error if passed an array.
    • The numerous implementations of this check have now been removed from the parsers inheriting from ValueParser

Author Checklist

  • Add unit test(s)
  • Update documentation (if necessary)
  • Update version in version.rb following versioning guidelines

@nicoledow nicoledow linked an issue Dec 1, 2023 that may be closed by this pull request
@@ -10,7 +10,7 @@ class ArrayParser < ValueParser
# Fetch parser classes for provided keys
parse_each = options.fetch(:parse_each, :pass)
item_parsers = Parser.parsers_for(Array.wrap(parse_each))
unless item_parsers.all? { |parser| parser <= ValueParser }
unless item_parsers.all? { |parser| parser <= ValueParser || parser <= PassParser }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to make PassParser inherit from Base so that it wouldn't throw an error when an array was passed to it. I then had to update this line to pass some specs that said all parsers must inherit from ValueParser.

I'm not totally clear on the purpose of PassParser, but it looks like it is used for values that should not be touched/transformed? If I'm understanding this correctly, it seems fine if it does not inherit from ValueParser and therefore does not run a check to ensure the passed value is not an array.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible that the PassParser has a defect where it doesn't have that guard clause, but should.

This is from the existing README:

Note: these parsers are designed to operate on a single value, except for :array. This parser expects an array, and will use the parse_each option to call a given parser on each of its elements:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the tests below from the pass_parser_spec tests, it seems PassParser is intended to accept an array (which conflicts with that blurb from the README):

it 'lets anything through' do
      expect(parser.parse(name, '(12)2-21/19.90')).to match({name =>'(12)2-21/19.90'})
 end

context 'with array value' do
      it 'returns the array value' do
        expect(parser.parse(name, ['123'])).to match({name => ['123']})
        expect(parser.parse(name, [])).to match({name => []})
      end
end

I think the result described by the test seems right - I'd expect to be able to pass any value if I had marked the key as :pass in my decanter. If this is right, maybe the right move is to update the README to indicate PassParser allows arrays?

Or, maybe the intended use for PassParser is to allow elements of an array to be any type (i.e. input :items, :array, parse_each: :pass), in which case we would want PassParser to only allow a singular value. In that case, I could update the specs.

Copy link
Contributor Author

@nicoledow nicoledow Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 The second option would be a breaking change

@nicoledow nicoledow marked this pull request as ready for review December 1, 2023 19:12
@nicoledow nicoledow requested a review from chawes13 as a code owner December 1, 2023 19:12
@@ -10,7 +10,7 @@ class ArrayParser < ValueParser
# Fetch parser classes for provided keys
parse_each = options.fetch(:parse_each, :pass)
item_parsers = Parser.parsers_for(Array.wrap(parse_each))
unless item_parsers.all? { |parser| parser <= ValueParser }
unless item_parsers.all? { |parser| parser <= ValueParser || parser <= PassParser }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible that the PassParser has a defect where it doesn't have that guard clause, but should.

This is from the existing README:

Note: these parsers are designed to operate on a single value, except for :array. This parser expects an array, and will use the parse_each option to call a given parser on each of its elements:

@@ -1,6 +1,6 @@
module Decanter
module Parser
class PassParser < ValueParser
class PassParser < Base
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above

super(name, value, options)
end

def self.validate_singularity(value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can / should we make this private?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. Done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor Value Parser
2 participants