首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何通过Rails API接受JSON而不使用嵌套字段的"_attributes“

如何通过Rails API接受JSON而不使用嵌套字段的"_attributes“
EN

Stack Overflow用户
提问于 2014-12-03 07:09:27
回答 2查看 5.4K关注 0票数 22

我已经用Rails编写了一个应用程序接口,需要在应用程序接口调用中接受一些nested_attributes。

目前我通过以下方式发送数据

vintages补丁/api/v1//1.json

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

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

vintages补丁/api/v1//1.json

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

区别在于属性是字段关键字的一部分。我希望能够在不使用_attributes的情况下将其作为JSON对象的一部分进行accept_nested_attributes_for :sizes

有人知道怎么处理这个问题吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-06 03:56:24

您可以自由地在您的强参数方法中执行一些魔术。根据您的需求,您的控制器中可能包含以下方法:

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来更改名称。

票数 32
EN

Stack Overflow用户

发布于 2015-07-06 12:08:08

我也在寻找一种方法来避免使用嵌套属性cruft来污染我的RESTful应用程序接口。我想我应该分享我的解决方案,因为它足够通用,对遇到同样问题的任何人都很有用。它从一个简单的模块开始,该模块可以从您的控制器中利用:

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

请注意,声明嵌套属性的语法反映了在控制器中声明允许的参数的语法。

Here's the Gist for this example.

我希望有人会发现这对我有帮助!

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27260756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档