ruby-grape / ruby-grape/grape

Array of hashes param not being parsed correctly in a spec

Open
#1,028 7 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

discuss!
Dominant language
Ruby
Stars
10k
Forks
1.2k
Avg merge
14h 38m
Merged PRs (30d)
92

Description

It might be a Rack issue, but:

before do
  subject.params do
    requires :contacts, type: Array do
      optional :name
      optional :phone
      optional :email
    end
  end

  subject.before_validation do
    pp form_vars: env['rack.request.form_vars'], form_hash: env['rack.request.form_hash']
    pp before: params.to_h
  end

  subject.post '/post' do
  end
end

it 'posts an array of hashes' do
  post '/post', contacts: [
    { name: 'John', phone: '123' },
    { email: 'a@mail.com' },
    { name: 'Doe', email: 'b@mail.com' },
  ]
end

Output is:

{:form_vars=>
  "contacts[][name]=John&contacts[][phone]=123&contacts[][email]=a%40mail.com&contacts[][name]=Doe&contacts[][email]=b%40mail.com",
 :form_hash=>
  {"contacts"=>
    [{"name"=>"John", "phone"=>"123", "email"=>"a@mail.com"},
     {"name"=>"Doe", "email"=>"b@mail.com"}]}}
{:before=>
  {"contacts"=>
    [{"name"=>"John", "phone"=>"123", "email"=>"a@mail.com"},
     {"name"=>"Doe", "email"=>"b@mail.com"}]}}

Rack(?) couldn't infer where each element starts so it combined both first items.

For a workaround I can send a Hash {0=>{name: ..., email:}, 1=>{email: ...}} and before validation do:

params[:contacts] = params[:contacts].values if params[:contacts].is_a?(Hash)

Any other suggestions?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the reproduction in the spec and inspect the request parameter handling around env['rack.request.form_vars'], env['rack.request.form_hash'], and params.to_h. Compare the submitted array-of-hashes form data with the parsed result; done means each contact remains a separate hash without requiring the workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.