为什么来自关系的 JSON 补丁数据无法通过 Rails 上的 Ruby 保存?

Why does the JSON patch data from relationships not get saved via Ruby on Rails?

我在 Rails api 上有一个 Ruby,其中数据在 JSON 中处理。当我想更新一个实体时,所有属性都在持续更新,但更改后的关系没有得到正确处理,该实体与以前一样。

JSON PATCH前后数据:

{"data":{"id":"26","type":"candidate","attributes":
{"place":"Ort","zip_code":"PLZ","address":"Adresse",
"date_of_birth":"2019-01-01T00:00:00.000Z","title":"Frau",
"first_name":"Vorname","last_name":"Nachname",
"email_address":"email@example.ch",
"confirm_terms_and_conditions":true},"relationships": 
{"occupational_fields":{"data":[]}}}}

补丁输入:

Started PATCH "/candidates/26" for 127.0.0.1 at 2019-01-22 
19:40:53 +0100
Processing by CandidatesController#update as JSON
Parameters: {"data"=>{"id"=>"26", "attributes"=>{"place"=>"Ort", 
"zip_code"=>"PLZ", "address"=>"Adresse", "title"=>"Frau", 
"first_name"=>"Vorname", "last_name"=>"Nachname", 
"email_address"=>"email@example.ch", 
"confirm_terms_and_conditions"=>true, "date_of_birth"=>"2019-01- 
01T00:00:00.000Z"}, "relationships"=>{"occupational_fields"=> 
{"data"=>[{"type"=>"occupational-fields", "id"=>“4“}]}}, 
"type"=>"candidates"}, "id"=>"26", "candidate"=>{}}

这是我的模型,Candidates 和 OccupationalFields 通过一个 CandidatesOccupationalField 的 has_many belongs_to_many 关系相关:

class Candidate < ApplicationRecord
  has_many :candidates_occupational_fields, dependent: :destroy
  has_many :occupational_fields, through: 
    :candidates_occupational_fields, dependent: :nullify
end


class CandidatesOccupationalField < ApplicationRecord
  belongs_to :candidate
  belongs_to :occupational_field
end


class OccupationalField < ApplicationRecord
  has_many :candidates_occupational_fields, dependent: :destroy
  has_many :candidates, through: :candidates_occupational_fields,
    dependent: :nullify
end

这是使用的控制器:

class CandidatesController < ApplicationController
  before_action :set_candidate, only: %i[show update destroy]

  # GET /candidates
  def index
    @candidates = Candidate.all
    render json: CandidateSerializer.new(@candidates).serialized_json
  end

  # GET /candidates/1
  def show
    @candidate = Candidate.find(params[:id])
    render json: CandidateSerializer.new(@candidate).serialized_json
  end

  # POST /candidates
  def create
    @candidate = Candidate.new(candidate_params)

    if @candidate.save
      render json: CandidateSerializer.new(@candidate), status: :created
    else
      render json: @candidate.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /candidates/1
  def update
    @candidate = Candidate.find(params[:id])
    if @candidate.update(candidate_params)
      render json: CandidateSerializer.new(@candidate)
    else
      render status: :unprocessable_entity
    end
  end

  # DELETE /candidates/1
  def destroy
    @candidate.destroy
  end

  private

  # Use callbacks to share common setup or constraints between actions.
  def set_candidate
    @candidate = Candidate.find(params[:id])
  end

  # Only allow a trusted parameter "white list" through.
  def candidate_params
    params.require(:data)[:attributes]
          .permit(:place, :zip_code, :address,
                  :date_of_birth, :title, :first_name,
                  :last_name, :email_address, 
                  :confirm_terms_and_conditions,
                  occupational_field_ids: [])
  end
end

JSON 格式由 fastjsonapi 处理,这是使用的序列化程序:

class CandidateSerializer
  include FastJsonapi::ObjectSerializer
  attributes :place, :zip_code, :address, :date_of_birth,
         :title, :first_name, :last_name, :email_address,
         :confirm_terms_and_conditions

  has_many :occupational_fields
end


class OccupationalFieldSerializer
  include FastJsonapi::ObjectSerializer
  attributes :field

  has_many :candidates
end

感谢您的帮助。

问题是,使用的序列化程序 fast_jsonapi can't be used as deserializer and the Rail's strong parameters can't handle the json input. It works with the gem restful-jsonapi 和修改的参数如 restful-jsonapi.

自述文件的示例所示