簡體   English   中英

如何通過Rails API接受JSON而不使用嵌套字段的“_attributes”

[英]How to accept JSON through Rails API without “_attributes” for nested fields

我用Rails編寫了一個API,需要在API調用中接受一些nested_attributes。

目前我通過發送數據

PATCH /api/v1/vintages/1.json

{
  "vintage": {
    "year": 2014,
    "name": "Some name",
    "foo": "bar",
    "sizes_attributes": [
      {
        "name": "large",
        "quantity": "12"
      },
      {
        "name": "medium",
        "quantity": "2"
      }
    ]
  }
}

但是,我想執行以下操作:

PATCH /api/v1/vintages/1.json

{
  "vintage": {
    "year": 2014,
    "name": "Some name",
    "foo": "bar",
    "sizes": [
      {
        "name": "large",
        "quantity": "12"
      },
      {
        "name": "medium",
        "quantity": "2"
      }
    ]
  }
}

區別在於屬性是字段鍵的一部分。 我希望能夠accept_nested_attributes_for :sizes而不必使用_attributes作為JSON對象的一部分。

誰知道如何管理這個?

您可以自由地在強參數方法中執行一些魔術。 根據您的需要,您可能在控制器中使用此方法:

def vintage_params
  params.require(:vintage).permit(:year, :name, :foo, { sizes: [:name, :quantity] })
end

您需要做的就是調整該方法中sizes鍵的名稱。 我建議:

def vintage_params
  vintage_params = params.require(:vintage).permit(:year, :name, :foo, { sizes: [:name, :quantity] })
  vintage_params[:sizes_attributes] = vintage_params.delete :sizes
  vintage_params.permit!
end

這將刪除:sizes鍵並將其放在預期的:sizes_attributes而不會弄亂你的漂亮的json。 您無法直接使用accepts_nested_attributes_for更改名稱。

我也在尋找一種方法來避免使用嵌套屬性cruft污染我的RESTful API。 我以為我會分享我的解決方案,因為它足以對遇到同樣問題的人有用。 它首先從您的控制器中利用一個簡單的模塊:

module PrettyApi
  class << self
    def with_nested_attributes(params, attrs)
      return if params.blank?

      case attrs
      when Hash
        with_nested_hash_attributes(params, attrs)
      when Array
        with_nested_array_attributes(params, attrs)
      when String, Symbol
        unless params[attrs].blank?
          params["#{attrs}_attributes"] = params.delete attrs
        end
      end
      params
    end

    private

    def with_nested_hash_attributes(params, attrs)
      attrs.each do |k, v|
        with_nested_attributes params[k], v
        with_nested_attributes params, k
      end
    end

    def with_nested_array_attributes(params, attrs)
      params.each do |np|
        attrs.each do |v|
          with_nested_attributes np, v
        end
      end
    end
  end
end

以下是在控制器中使用此模塊的示例,用於從移動客戶端上載通訊簿:

class V1::AddressBooksController < V1::BaseController
  def create
    @address_book = AddressBook.new address_book_params
    unless @address_book.save
      errors = @address_book.errors.to_hash(true)
      render status: 422, json: { errors: errors }
    end
  end

  private

  def address_book_params
    PrettyApi.with_nested_attributes  pretty_address_book_params,
                                      contacts: [:emails, :phones, :addresses]
  end

  def pretty_address_book_params
    params.permit(
      :device_install_id,
      contacts: [
        :local_id,
        :first_name,
        :last_name,
        :nickname,
        emails: [
          :value,
          :type
        ],
        phones: [
          :value,
          :type
        ],
        addresses: [
          :type,
          :street_address,
          :city,
          :state,
          :postal_code,
          :country
        ]
      ]
    )
  end
end

請注意,聲明嵌套屬性的語法反映了在控制器中聲明允許的參數的語法。

這是這個例子的要點。

我希望有人覺得這很有用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM