I am trying to create multiple database entries using only one JSON request. Each entry consists only of two values, a type (of action) and a time (when the action happened). To get multiple of those into one request, I am using a JSON Array.
This is what my create action in the controller looks like:
def create
respond_to do |format|
@actions = []
save_succeeded = true
params[:action].each do |action|
new_action = Action.new(type: action.type, time: action.time)
save_succeeded = false unless new_action.save
@actions << new_action
end
if save_succeeded
format.json { render json: @actions, status: :created }
else
format.json { render json: @actions.errors, status: 501 }
end
end
end
When I send a post request to the controller ( /actions.json
) like this:
[{ "type": 0, "time": 1234567890 },{ "type": 0, "time": 1234567891 }]
I get back an empty array []
and a status code of 201 Created
.
This means, the save_succeeded
variable is still true, but the actions did not get added to the array. Furthermore, the actions are not in my database.
What am I doing wrong? What am I overlooking?
I would refactor the code a bit:
def create
actions = params[:action].inject([]) do |memo, action|
memo << Action.create!(type: action[:type], time: action[:time])
end
render json: @actions, status: :created
rescue ActiveRecord::RecordInvalid => e
render json: e.message, status: 501
end
end
Couple of notable changes:
use create!
and rescue ActiveRecord::RecordInvalid
- create!
will raise a ActiveRecord::RecordInvalid
if the save fails. Then, the rescue block will rescue the exception and you can render a nice error message.
you cannot use action.time
, because params
is a Hash, not an object.
if you want to build an array to render later, you can use inject .
if you would like to have some atomicity to this (either everything is created or nothing!), you can wrap the whole thing in a transaction block.
It's worth mentioning that I haven't tested the code above, but it should give you a direction and (maybe) it will be a drop-in replacement.
Hope that helps!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.