Deovandski
Deovandski

Reputation: 790

Deserializing Json-Api with Rails Strong Parameters

I am using Active Model Serializers 0.10.x with EmberCLI and Rails while trying to have the Json-Api as the Adapter. GET requests are working, but deserialization for the Active Model is not even though I tried to implement the rails strong_parameters solution described by jimbeaudoin here.

My latest attempt in saving a comment:

Payload:

{"data":{
   "attributes": {"soft_delete":false,"soft_delete_date":null,"text":"hjfgfhjghjg","hidden":false,"empathy_level":0},
   "relationships":{
     "user":{"data":{"type":"users","id":"1"}},
     "post":{"data":{"type":"posts","id":"1"}}},"type":"comments"}}

Console Output:

Completed 400 Bad Request in 13ms (ActiveRecord: 8.6ms)
ActionController::ParameterMissing (param is missing or the value is empty: data):

Comments Controller:

class Api::V1::CommentsController < MasterApiController
    respond_to :json
    ...
    def create
        render json: Comment.create(comment_params)
    end
    ...
    def comment_params
        #Deserialization issues... Waiting for #950 https://github.com/rails-api/active_model_serializers/pull/950
        params.require(:data).require(:attributes).permit(:text, :user_id, :post_id, :empathy_level, :soft_delete_date, :soft_delete, :hidden)
    end
end

Noting that if I set the parameters to only params.permit(...), the server saves it with everything null (I did not set any constraints on the comments model for now):

data: {id: "9", type: "comments",…}
attributes: {soft_delete: null, soft_delete_date: null, text: null, hidden: null, empathy_level: null}
id: "9"
relationships: {post: {data: null}, user: {data: null}}
type: "comments"

You can access the full code here.

Upvotes: 23

Views: 8088

Answers (4)

Deovandski
Deovandski

Reputation: 790

Update #2: For AMS >= 0.10.2, please check other answers.

Update #1: Answer is still valid for AMS 0.10.1.

If you use 0.10.0.rc4, you can now use the Deserialization implementation described on Active Model Serializers #1248.

def post_params
    ActiveModel::Serializer::Adapter::JsonApi::Deserialization.parse(params.to_h) 
    // or (params.to_unsafe_h) in some cases like in my example below...
end

Bonus: If you use Ember Data, then you can see an example implementation on my Fakktion Github repo.

Upvotes: 13

XYZ
XYZ

Reputation: 27397

With AMS 0.10.2+

Use only hash to create a parameter whitelist,

def post_params
  ActiveModelSerializers::Deserialization.jsonapi_parse!(
    params, only: [:title, :author, :tags]
  )
end

Upvotes: 8

rolkos
rolkos

Reputation: 342

For AMS >= 0.10.2

In 0.10.2 there was a cleanup so after 0.10.2 use:

def post_params
   ActiveModelSerializers::Deserialization.jsonapi_parse(params)
end

Reference: https://github.com/rails-api/active_model_serializers/commit/252f9c4ae932e6280dfe68605d495b208fe22ba7

Upvotes: 8

qnsi
qnsi

Reputation: 380

For googlers:

If you have empty data payload, you need to add Mime support https://stackoverflow.com/a/32013294/2664779

When you want to access json-api formatted json, you should do it like this (in your controller)

def create   
  user = User.new(user_params)
...
end

private

  def user_params
    params.require(:data).require(:attributes).permit(:email, :password)
  end

When previously I would do it like this

private

def user_params
  params.require(:user).permit(:email, :password)
end

Upvotes: 4

Related Questions