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?
答案 0 :(得分:0)
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!