我正在用ruby、grape和activerecord构建一个web api。来自asp.net web api,我习惯了从json到类对象的自动模型绑定,然后可以用实体框架保存。在使用activerecord时,我一直在寻找是否有类似的东西,但是没有发现任何东西让我觉得我遗漏了一些非常明显的东西。将json反序列化为activerecord模型的最佳方法是什么?
更新
matts answer对于简单类型很有用,但是当我有关联时,我会得到以下错误:activerecord::associationtypemismatch:connector(7029771166780)应为,got hash()
这是我运行的代码

class Card < ActiveRecord::Base
   has_many    :connectors, autosave: true
end

class Connector < ActiveRecord::Base
   has_one  :card
   has_one  :connected_card, :class_name => "Card", :foreign_key => "connected_card_id"
end

json = "{\"id\":\"1\", \"connectors\": [{\"id\": 1, \"card_id\":1}]}"
card = Card.new(ActiveSupport::JSON.decode(json))

最佳答案

在模型中,您创建了一个名为connectors的关联。这是一个Card方法,它将需要来自类ActiveRecord::Relation的一组模型。否则,您将传递一个散列数组。

{"id"=>"1", "connectors"=>[{"id"=>1, "card_id"=>1}]}

在您的Connector方法中,这变得类似于:
Card.new(id: 1, connectors: [{id: 1, card_id: 1}])

一旦到达那里,连接器数组应该填充连接器实例,而不是散列。这就是失败的原因。
你有两个选择。首先是在控制器的before_操作中重命名键并使用嵌套属性:
class Card < ActiveRecord::Base
  has_many :connectors
  accepts_nested_attributes_for :connectors
end

class CardsController < ApplicationController
  before_action :set_nested

  private
  def set_nested
    params["connectors_attributes"] = params.delete("connectors")
  end
end

另一个选项是在模型中创建回调,以从散列创建对象。
class Card < ActiveRecord::Base
  def initialize(params={})
    params["connectors"] = params["connectors"].map {|connector| Connector.new(connector)}
    super(params)
  end
end

以上任何一项都能满足你的需要。我认为最好的是第一个,因为你不会重新定义#new

07-24 18:04
查看更多