Reputation: 102
I have in my Rails 5 api project two models: Places and Beacons (Place has_many Beacons, foreign key: place_id). This API accepts JSON, such as this one:
{
"place":{
"name": "bedroom"
},
"beacon":{
"SSID": "My Wi-Fi",
"BSSID": "00:11:22:33:44:55",
"RSSI": "-55"
}
}
This JSON works just fine, with these classes:
def create
@place = Place.new(place_params)
@beacon = Beacon.new(beacon_params)
if @place.save
@[email protected]
if @beacon.save
render :json => {:place => @place, :beacon => @beacon}, status: :created, location: @places
else
render json: @beacon.errors, status: :unprocessable_entity
end
else
render json: @place.errors, status: :unprocessable_entity
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_place
@place = Place.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def place_params
params.require(:place).permit(:name)
end
def beacon_params
params.require(:beacon).permit(:SSID, :BSSID, :RSSI)
end
However, I want that to pass multiple Beacons objects in the same JSON in an array (even no beacons at all). How can I save then all beacons in the parameter array and generate a response containing all of them?
Upvotes: 1
Views: 1359
Reputation: 191
I'm assuming Place has_many :beacons
. If so, you can use nested attributes. This lets you assign and update a nested resource, in this case Beacons. First, in your Place
model:
accepts_nested_attributes_for :beacons
Then, change your place_params
method in your controller to permit the beacon's nested attributes:
def place_params
params.require(:place).permit(:name, beacons_attributes: [:id, :SSID, :BSSID, :RSSI])
end
And your json:
{
"place":{
"name": "bedroom",
"beacons_attributes": [
{
"SSID": "My Wi-Fi",
"BSSID": "00:11:22:33:44:55",
"RSSI": "-55"
}, {
//more beacons here
}
]
},
}
You can have zero, one, or more beacons, and can do the same when updating as well if you include the beacons' id's.
You also won't have to create the @beacon manually, and can just do this: @place = Place.new(place_params)
, and it'll automatically create the beacons and associate them to the Place.
You can read more here, if you'd like more information or clarification: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
Edit: I missed where you asked how to include the beacons in the response. The quickest way is to just include it in the json rendering:
render :json => @place.to_json(:include => :beacons)
You can use Active model serializers (https://github.com/rails-api/active_model_serializers), jbuilder (https://github.com/rails/jbuilder), or more simply just override the to_json
method on your model.
Upvotes: 1