繁体   English   中英

如何在Ruby on Rails中收到嵌套属性的JSON:API帖子?

[英]How can I receive a JSON:API post of nested attributes in Ruby on Rails?

是否有一种“标准”方法来接收(可能嵌套)Rails中的JSON:API POST对象?

JSON:API规范对GET / POST / PUT等使用相同的格式,但rails似乎需要* _attributes和accepts_nested_attributes_for。 这些似乎不相容。

我觉得我正在做的事情必须有点普遍,但我找不到文档。 我想使用React / Redux应用程序,它使用JSON:API规范与Rails应用程序通信。 我只是不确定如何处理嵌套关联。

您可以使用active_model_serializer gem的反序列化功能。

来自gem的文档

class PostsController < ActionController::Base
  def create
    Post.create(create_params)
  end

  def create_params
    ActiveModelSerializers::Deserialization.jsonapi_parse(params, only: [:title, :content, :author])
  end
end

以上可以使用以下JSON API有效负载:

document = {
  'data' => {
    'id' => 1,
    'type' => 'post',
    'attributes' => {
      'title' => 'Title 1',
      'date' => '2015-12-20'
    },
    'relationships' => {
      'author' => {
        'data' => {
          'type' => 'user',
          'id' => '2'
        }
      },
      'second_author' => {
        'data' => nil
      },
      'comments' => {
        'data' => [{
          'type' => 'comment',
          'id' => '3'
        },{
          'type' => 'comment',
          'id' => '4'
        }]
      }
    }
  }
}

可以在不指定任何选项的情况下解析整个文档:

ActiveModelSerializers::Deserialization.jsonapi_parse(document)
#=>
# {
#   title: 'Title 1',
#   date: '2015-12-20',
#   author_id: 2,
#   second_author_id: nil
#   comment_ids: [3, 4]
# }

我看到这些多头线程/问题的讨论#979#795的JSON:API回购天前,即aparently似乎JSON API没有一个真正的解决方案accepts_nested_attributes_for

我不知道它是否是更好的解决方案,但解决方法是将路由部署到belongs_tohas_many/has_one关联。

像这样的东西:

你的routes.rb

Rails.application.routes.draw do
  resources :contacts do
    resource :kind, only: [:show]
    resource :kind, only: [:show], path: 'relationships/kind'

    resource :phones, only: [:show]
    resource :phones, only: [:show], path: 'relationships/phones'

    resource :phone, only: [:update, :create, :destroy]
    # These relationships routes is merely a suggestion of a best practice
    resource :phone, only: [:update, :create, :destroy], path: 'relationships/phone'

    resource :address, only: [:show, :update, :create, :destroy]
    resource :address, only: [:show, :update, :create, :destroy], path: 'relationships/address'
  end

  root 'contacts#index'
end

他们实现你的控制器 以上示例后面的phones_controller.rb

class PhonesController < ApplicationController
  before_action :set_contacts

  def update
    phone = Phone.find(phone_params[:id])

    if phone.update(phone_params)
      render json: @contact.phones, status: :created, location: contact_phones_url(@contact.id)
    else
      render json: @contact.errors, status: :unprocessable_entity
    end
  end

  # DELETE /contacts/1/phone
  def destroy
    phone = Phone.find(phone_params[:id])
    phone.destroy
  end

  # POST contacts/1/phone
  def create
    @contact.phones << Phone.new(phone_params)

    if @contact.save
      render json: @contact.phones, status: :created, location: contact_phones_url(@contact.id)
    else
      render json: @contact.errors, status: :unprocessable_entity
    end
  end

  # GET /contacts/1/phones
  def show
    render json: @contact.phones
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_contacts
      @contact = Contact.find(params[:contact_id])
    end

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

通过这样做,您应该能够通过联系人单独请求电话POST ,如下所示:

POST :http:// localhost:3000 / contacts / 1 / phone with body:

{
    "data": {
            "type": "phones",
            "attributes": {
                "number": "(+55) 91111.2222"
            }
    }
}

http:// localhost:3000 / contacts / 1 / phones上的响应或GET:

{
    "data": [
        {
            "id": "40",
            "type": "phones",
            "attributes": {
                "number": "(55) 91111.2222"
            },
            "relationships": {
                "contact": {
                    "data": {
                        "id": "1",
                        "type": "contacts"
                    },
                    "links": {
                        "related": "http://localhost:3000/contacts/1"
                    }
                }
            }
        }
    ]
}

希望能回答

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM