我正在尝试向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
我正在尝试的是什么?
答案 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中完美地(一如既往)解释了嵌套模型的形式。