使用关联数据发布JSON

时间:2012-06-25 19:42:16

标签: ruby-on-rails ruby-on-rails-3 json rest

我正在尝试向rails scaffold控制器发送POST请求,该控制器包含一个嵌套数组,表示需要创建并与新创建的父关联的记录。

以下是JSON的一些示例:

{
    "plan_id":3,
    "weight":60,
    "exercise_sets": [
        {
            "created_at":"2012-06-13T14:55:57Z",
            "ended_at":"2012-06-13T14:55:57Z",
            "weight":"80.0",
            "repetitions":10,
            "exercise_id":1
        }
    ]
}

..和我的模特..

class Session < ActiveRecord::Base
  has_many :exercise_sets, :dependent => :destroy
  has_many :exercises, :through => :exercise_sets
end

class ExerciseSet < ActiveRecord::Base
  belongs_to :exercise
  belongs_to :session
end

我正在尝试的是什么?

2 个答案:

答案 0 :(得分:5)

这当然不是不可能的,尽管您可能需要稍微调整参数命名。

当您将上面的JSON传递给控制器​​时,它将作为参数传递给构造函数:

Session.new(params[:session])

或者传递给持久化Session实例上的#update_attributes方法:

@session = Session.find(params[:id])
@session.update_attributes(params[:session])

构造函数和#update_attributes方法都将“plan_id”之类的参数转换为assigment方法调用。也就是说,

@session.update_attributes(:plan_id => "1")  

变成(#update_attributes方法内部):

@session.plan_id = "1"

因此,这适用于您的plan_id和weight属性,因为您同时拥有#plan_id =和#weight = setter方法。您还有has_many :exercise_sets给您的#exercise_sets =方法。但是,#exercise_sets =方法需要ExerciseSet对象,不是ExerciseSet属性

Rails能够通过#accepts_nested_attributes_for类方法执行您要执行的操作。试试这个:

class Session < ActiveRecord::Base
  has_many :exercise_sets, :dependent => :destroy
  has_many :exercises, :through => :exercise_sets

  accepts_nested_attributes_for :exercise_sets
end

这为您设置(元程序)#exercise_sets_attributes =方法。所以只需将您的JSON修改为:

{
    "plan_id":3,
    "weight":60,
    "exercise_sets_attributes": [
        {
            "created_at":"2012-06-13T14:55:57Z",
            "ended_at":"2012-06-13T14:55:57Z",
            "weight":"80.0",
            "repetitions":10,
            "exercise_id":1
        }
    ]
}

更多信息:http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

答案 1 :(得分:0)

完全有可能,您只需将以下行添加到Session模型中:

  accepts_nested_attributes_for :exercise_sets, :reject_if => lambda { |a| a[:exercise_id].blank? }, :allow_destroy => true

现在,当您的控制器执行Session.new(params[:session])时,Rails将构建(或更新)Session 相关的ExerciceSet

请查看:reject_if条款。这就是你定义哪些记录将被创建而哪些不会被创建的地方。

这是基础知识,但Ryan Bates在this screencast中完美地(一如既往)解释了嵌套模型的形式。