0

I have a simple API built using

rails new my_api --api

Then

rails g scaffold Model name age

I can make a new record using curl POST request like so

curl -H "Accept: application/json" -H "Content-type: application/json" -d '{"name": "Fred", "age": "5"}' "http://localhost:3000/model_name"

Question

Is it possible to submit multiple new records in the same POST request? And if so, what should the JSON look like?

What I've tried so far

I've tried variations of {"name": "Fred", "age": "5"}, like {"name": ["Fred", "Mary"], "age": ["5", "6"]}

The API doesn't reject this JSON, instead, it creates 1 record (not 2), and the values are nil instead of the actual data.

Note

The current controller code is

  def create
    @model = Model.new(model_params)

    if @model.save
      render json: @model, status: :created, location: @model
    else
      render json: @model.errors, status: :unprocessable_entity
    end
  end
Community
  • 1
  • 1
stevec
  • 41,291
  • 27
  • 223
  • 311

1 Answers1

2

Short answer, yes.

You built the API, you define exactly what that POST request will receive and how it will handle it. Rails scaffold auto generated create method will not accept multiple records at once in a JSON though. You must open the controller file that was generated by rails scaffold and change it to accept multiple records.

And a little hint, try this structure for a JSON with multiple records:

[{"name": "Fred", "age": "5"}, {"name": "Fred", "age": "5"}, {"name": "Fred", "age": "5"}]
Lucas Wieloch
  • 818
  • 7
  • 19
  • I popped the controller code into the question above. Is it possible to show a minimal implementation of what you suggest? – stevec Jul 10 '19 at 08:53
  • Just remove the line `@model = Model.new(model_params)` and change the `if @model.save` to `if Model.create(model_params)`. That should do the trick, although I am pretty sure you need to change your `model_params` method to permit the new `JSON` array of params. Check [docs](https://guides.rubyonrails.org/action_controller_overview.html) for that, they are very helpful – Lucas Wieloch Jul 10 '19 at 09:14
  • I will try now. – stevec Jul 10 '19 at 09:15
  • I made the changes to the controller. But I get `Completed 400 Bad Request in 10ms (ActiveRecord: 32.1ms)` Followed by `ActionController::ParameterMissing (param is missing or the value is empty: model`. I cannot see in the docs how to modify `model_params` to accept a JSON array? The current method is `params.require(:model).permit(:name, :age)` – stevec Jul 10 '19 at 09:21
  • See [here](https://stackoverflow.com/questions/56967541/how-to-alter-params-method-to-accept-a-json-array-in-rails-controller) – stevec Jul 10 '19 at 09:24
  • `params.permit([:name, :age])`. See [this](https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-require) to understand what `require` method does. In that topic you have linked it is mentioned why you got that error. Basically, `require` would ask for a different `JSON` structure such as `{ "model" : [{"name": "Fred", "age": "5"}, {"name": "Fred", "age": "5"}, {"name": "Fred", "age": "5"}]}` – Lucas Wieloch Jul 10 '19 at 09:41
  • I now see `(undefined method permit?' for # Did you mean? permutation):` – stevec Jul 10 '19 at 09:55
  • I checked [here](https://stackoverflow.com/questions/16549382/how-to-permit-an-array-with-strong-parameters) and indeed it is wrong. If you want to call permit for each element in the array of params, you should loop in that array, instance a new `ActionController::Parameters` and call `permit(:name, :age)` in each one. If you don't want to sanitise params (highly unsafe) you can just change the line `Model.create(model_params)` to `Model.create(params)` – Lucas Wieloch Jul 10 '19 at 10:15