rails和嵌套属性

时间:2013-07-09 20:03:47

标签: ruby-on-rails-3 ruby-on-rails-3.2

我正在构建一个Rails API,并希望尽可能简单。我想要完成的一件事是获得尽可能自然的JSON。例如:

company: {
   name: 'company one',
   addresses: [{ name: 'address1'}, { name: 'address2'}]
}

这不起作用,因为地址是嵌套模型,需要名称为'addresses_attributes'。我想摆脱posfix'_attributes'。

知道怎么做吗?有没有宝石?

1 个答案:

答案 0 :(得分:0)

好吧,我编写了一个简单的类。不是世界上最好的代码,但它有效

# nested attributes module
module Api
  module NestedAttributes
    # check for nested attributes
    # transform parameters like this:
    # company: { name: 'test1', address: [{name: 'name1'}]}
    # To
    # company: { name: 'test1', address_attributes: [{name: 'name1'}]}
    def transform params, attributes = []
      apply params, attributes
      return params
    end

    private

    def generate_key key
      "#{key.to_s}_attributes".to_sym
    end

    def apply params, attributes
      case attributes
      when Array
        apply_array params, attributes
      when Symbol
        apply_symbol params, attributes
      when Hash
        apply_hash params, attributes
      end
    end

    def apply_array params, array
       # return the params if the attributes are empty
      return params if array.empty?
      # for each array value
      array.each do |value|
        apply params, value
      end
    end

    def apply_hash params, hash
       # return the params if the attributes are empty
      return params if hash.empty?
      # for each key
      hash.each_key do |key|
        # the new key name
        new_key = generate_key key
        if params.has_key? key
          # delete the key and assigned the value to the new key
          params[new_key] = params.delete(key)
          apply params[new_key], hash[key]
        end
      end
    end

    def apply_symbol params, symbol
      if params.is_a? Array
        params.each { |p| apply_symbol p, symbol}
      else
        if params.has_key? symbol
          new_key = generate_key symbol
          # delete the key and assigned the value to the new key
          params[new_key] = params.delete(symbol)
        end
      end
    end

  end
end

用法:

class Test
 include Api:NestedAttributes

 def test
  params = { company: { options: {}}}
  transform params, company: options
  # result => { company_attributes: { options_attributes: {}}}
 end

end