以下是我多对多关系中的模型:
class Student < ActiveRecord::Base
has_many :classroom_memberships, :dependent => :destroy
has_many :classrooms, :through => :classroom_memberships
end
class ClassroomMembership < ActiveRecord::Base
belongs_to :classroom
belongs_to :student
end
class Classroom < ActiveRecord::Base
has_many :classroom_memberships
has_many :students, :through => :classroom_memberships
end
在创建新学生时,我希望让用户能够选择多个教室以及即时创建新教室。
(我已经能够通过一对多关系来实现这一点。)
以下是我目前在学生表格中的内容:
<%= f.association :classrooms,
collection: Classroom.all(order: 'name'),
prompt: "Choose or type a new classroom name",
multiple: true,
input_html: { :class => "shown" } %>
这允许我做这个漂亮的多选框(使用selectize.js):
当我提交表格时,通过的参数是:
=> {
"first_name" => "Tyene",
"last_name" => "Sand",
"birthday" => "January 1, 2013",
"gender" => "F",
"about_me" => "",
"family_id" => "1",
"classroom_ids" => [
[0] "",
[1] "1",
[2] "2"
]
}
当调用Student.new(student_params)
时,Rails神奇地知道在classroom_memberships
表中创建2条新记录,一切都很好。
但是,如果我让用户在列表中添加一个全新的教室,Rails会抛出此错误:
Couldn't find all Classrooms with IDs (1, 2, 0) (found 2 results, but was looking for 3)
显然,如果没有为选择列表中的第三项创建新的classroom_memberships
,它就无法创建classroom
记录。
如何(或在哪里)可以插入一些代码来检查参数中的classroom_ids
列表,并在Rails检查之前创建classroom
记录以查看classroom_id
存在吗
我尝试将代码放在classroom_membershp.rb
模型中,如下所示:
def classroom_id=(val)
# if we've got an integer, they selected an existing record;
# otherwise, we're creating a brand new one
if val.numeric?
write_attribute(:classroom_id, val.to_i)
else
create_classroom(:name => val)
end
end
但代码永远不会到达!它尝试在此之前通过classroom
找到SELECT
并炸毁。这种方法在一对多关系中对我有用。
/app/models/student.rb
中的:
def self.init(params)
params[:classroom_ids].each_with_index do |c, i|
# a non-blank, non-numeric classroom ID indicates a new record
if !c.blank? && !c.numeric?
params[:classroom_ids][i] = Classroom.create(:name => c).id
end
end
new(params)
end
我现在正在Student.init(student_params)
和create
行动中致电update
。
这种方法的唯一缺点是即使学生创作失败也会创建课堂。对于我的申请,这没关系。
答案 0 :(得分:1)
我会在Student
类
def self.init(params)
if i = params[:classroom_ids].find_index(&:empty?)
params[:classroom_ids][i] = create_classroom
end
new(params)
end