Reputation: 889
I am working to an REST API in Rails 4.2 and I want to respect JSON API format. My params are like this:
{
"data":{
"type": "articles",
"id": "1",
"attributes": {
"title": "this is title",
"description": "This is description"
}
}
I tried to write a method for strong params like this:
def article_params
params.require(:data).permit(:id, attributes: [:title, :description])
end
but when I try to do Article.update_attributes(article_params)
it says title and description parameters not permitted
[My Article model has title and description]. Can you help me?
Upvotes: 18
Views: 14500
Reputation: 2526
I guess the best way to achieve that now is :
added
gem 'active_model_serializers'
to your Gemfile
and this on your controller
ActiveModelSerializers::Deserialization.jsonapi_parse(params)
bonus handle dash for you.
params = { "data": {
"attributes": {
"title": "Bucket List",
"created-by": "John Doe"
},
"type": "todos"
}
}
params = ActionController::Parameters.new(params)
ActiveModelSerializers::Deserialization.jsonapi_parse(params)
=> {:title=>"Bucket List", :created_by=>"John Doe"}
Upvotes: 5
Reputation: 560
You could also use a json:api library which provides deserialization capabilities, such as http://jsonapi-rb.org, so that you do not have to deal with the json:api format directly. In that context, your example would read:
class ArticlesController < ApiController
deserializable_resource :article, only: [:create, :update]
def article_params
params.require(:article).permit(:title, :description)
end
# ...
end
Upvotes: 0
Reputation: 102036
Dealing with JSONAPI params is only slightly different than dealing with the usual Rails params hashes:
class ArticlesController < ApiController
before_filter :set_article, only: [:show, :edit, :update, :destroy]
# POST /api/v1/articles
def create
@article = Article.new(article_attributes)
# ...
end
# PATCH /api/v1/articles/:id
def update
@article.update(article_attributes)
# ...
end
# ...
private
def set_article
@article = Article.find(params[:id])
end
def article_attributes
params.require(:data)
.require(:attributes)
.permit(:title, :description)
end
end
First thing you should notice here is that we are not even using params[:data][:id]
key from the JSON data at all since the ID is available from the request url (params[:id]
). If you follow RESTful patterns chances are that you never will need to use the params[:data][:id]
parameter.
In article_attributes
we are using nested require calls because we want Rails to raise an ActionController::ParameterMissing
error unless the provided JSON data confirms to the JSON API spec. The vanilla Rails default is to rescue with a 400 Bad Request response - RailsAPI will return 422 and an JSON error object if it is properly set up for JSONAPI which is what we want.
Upvotes: 23