ruby-grape / grape

An opinionated framework for creating REST-like APIs in Ruby.
http://www.ruby-grape.org
MIT License
9.89k stars 1.22k forks source link

Error when validating array items with different conditionally required properties #2473

Open dub-wt opened 3 months ago

dub-wt commented 3 months ago

Hello,

If we define different properties required for array items by given condition then validation fails even if correct request is sent.

Please check the example below:

it 'test to demonstrate the validation issue' do
  subject.params do
    requires :a, type: String, allow_blank: false, values: %w[x y z]
    given a: ->(val) { val == 'z' } do
      requires :inner3, type: Array, allow_blank: false do
        requires :bar, type: String, allow_blank: false

        given bar: ->(val) { val == 'b' } do
          requires :baz, type: Array do
            requires :new_category, type: String
          end
        end

        given bar: ->(val) { val == 'c' } do
          requires :baz, type: Array do
            requires :baz_category, type: String
          end
        end

      end
    end
  end
  subject.post('/nested-dependency') { declared(params).to_json }

  test = {
    a: 'z',
    inner3: [
      { bar: 'b', baz: [{ new_category: 'nope' }] },
      { bar: 'c', baz: [{ baz_category: 'nope' }] }
    ]
  }

  post '/nested-dependency', **test

  expect(last_response.status).to eq(200)
end

Expected behavior: 200 OK

Actual behavior: 400 Bad request, "inner3[1][baz][0][new_category] is missing, inner3[1][baz][0][baz_category] is missing"

Thank you.

dblock commented 3 months ago

Check whether this is still the behavior on HEAD and turn it into a (failing) PR/spec?

Note that your post may need a correct content-type, transforming what you post to a string, this may be a side-effect of form encoding.

dub-wt commented 3 months ago

I checked it on the latest commit and just have rechecked with passing Content-Type = application/json.
Validation fails.

dub-wt commented 3 months ago

Here is the PR with failing spec: https://github.com/ruby-grape/grape/pull/2474

dub-wt commented 3 months ago
params do
        requires :items, type: Array, allow_blank: false do
          requires :item_type, type: String, allow_blank: false

          given item_type: ->(val) { val == 'type_a' } do
            requires :inner_items, type: Array do
              requires :prop_a, type: String
            end
          end

          given item_type: ->(val) { val == 'type_b' } do
            requires :inner_items, type: Array do
              requires :prop_b, type: String
            end
          end
        end
      end

Looks like condition given item_type: ->(val) { val == 'type_a' } is ignored when validating nested array properties.
They are always validated, but it should happen when item_type meets dependency.

dblock commented 3 months ago

Looks like condition given item_type: ->(val) { val == 'type_a' } is ignored when validating nested array properties. They are always validated, but it should happen when item_type meets dependency.

And it works for nested hashes? Want to try to fix it?

dub-wt commented 3 months ago

No, it also doesn't work for nested hashes. Sure, will try to fix it.