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

Fix Undefined method `key?' for nil:NilClass error. #672

Merged
merged 2 commits into from
Sep 23, 2020

Conversation

alexxty7
Copy link
Contributor

Fixes #670

Copy link
Member

@solnic solnic left a comment

Choose a reason for hiding this comment

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

Thanks for addressing this! I need to clarify one thing before this can be merged, please see my question in the review.

@@ -70,6 +70,8 @@ def key?(key, hash = data)
return result
elsif e.is_a?(Symbol) && a.is_a?(Array)
return false
elsif a.is_a?(String) || a.nil?
return false
Copy link
Member

Choose a reason for hiding this comment

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

Why a.is_a?(String) was needed? It shouldn't be, at this point all keys should be symbolized.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It for the case when root value is a string. I have checked and it is not symbolized.
It covered by this test case

  let(:data) do
    {
      name: "Jane",
      address: {city: "Paris", geo: {lat: 1, lon: 2}},
      phones: [123, 431],
      billing_address: nil,
      card: ""
    }
  end

    it "returns false when a nested key is not present and root key is string" do
      expect(values.key?([:card, :not_here])).to be(false)
    end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe I should check for valid types instead?

          elsif !(a.is_a?(Array) || a.is_a?(Hash))
            return false

Copy link
Member

Choose a reason for hiding this comment

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

@alexxty7 aahh that's right, this can happen! I think it should be handled separately though, so:

# ...
elsif a.nil?
  return false
elsif a.is_a?(String)
  return false
# ...
end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@solnic updated

Copy link
Member

@solnic solnic left a comment

Choose a reason for hiding this comment

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

Thank you!

@solnic solnic merged commit 0f04a17 into dry-rb:master Sep 23, 2020
@TimoMoss
Copy link

TimoMoss commented Nov 29, 2020

hello,
I have a similar problem when I use a rule for each element of an array.
dry-validation '~> 1.4'

ValidateParams < Dry::Validation::Contract
    schema do
        required(:data).hash do
          required(:attributes).hash do
            required(:items).array(:string)
         end
       end
    end

    rule(%i[data attributes items]).each do
       message = 'invalid numeric string'
       key(keys.flatten).failure(message) if value&.!~ /^(\d)+$/
    end
 end
RSpec.describe ValidateParams do
  let(:validation) { described_class.new }

  let(:params) do
    {
        data: {
            attributes: {
               items: ['123', '123', '123']
            }
        }
    }
  end

  it 'looks like failure' do
    expect(validation.call(params)).to be_failure
  end
end

result

>>  Failure/Error: expect(validation.call(params)).to be_failure
     NoMethodError:
       undefined method `key?' for nil:NilClass

at the moment I have it solved by:

      rule(%i[data attributes items]) do
         value.each_with_index do |v, i|
           message = 'invalid numeric string'
           key(keys.flatten << i).failure(message) if v&.!~ /^(\d)+$/
        end
      end

But it's definitely a trick.
I'd highly appreciate it if anybody explains how can I make it work without such tricks.
Many thanks in advance

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.

Rule#each. Undefined method `key?' for nil:NilClass
3 participants