kitz
kitz

Reputation: 889

Strong parameters JSON API rails

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

Answers (3)

Joel AZEMAR
Joel AZEMAR

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

beauby
beauby

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

max
max

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

Related Questions