在下面提供的exaple中,我需要在创建或更新Course对象时自动设置Training join模型的属性角色.
这是我的模特:
QUAliFICATIONS = ["Theoretical Instructor","Practical Instructor"]class Course < ActiveRecord::Base has_many :trainings,dependent: :destroy has_many :theoretical_instructors,through: :trainings,source: :trainer,conditions: { "trainings.role" => "Theoretical Instructor" } accepts_nested_attributes_for :theoretical_instructors has_many :practical_instructors,conditions: { "trainings.role" => "Practical Instructor" } accepts_nested_attributes_for :practical_instructorsendclass Trainer < ActiveRecord::Base has_many :trainings,dependent: :destroy has_many :courses,through: :trainingsendclass Training < ActiveRecord::Base belongs_to :trainer belongs_to :course # Join model has the :role attribute,that I wish I Could valIDate this way: # valIDates :role,presence: true,inclusion: { in: QUAliFICATIONS }end
这个模型背后的基本原理是我想将Training对象保存在一个表中.我不想创建Theoreticalinstructor和Practicalinstructor连接模型(可能爆炸表的数量)来解决这个问题.
此视图提供了提交新课程的表单:
<%= form_for @course do |course_form| %> <%- # fIElds for course attributes,as usual... %> <%= course_form.label :theoretical_instructor_IDs %><br /> <%= course_form.select :theoretical_instructor_IDs,Trainer.all.map { |x| [[x.name,x.surname].join(" "),x.ID] },{ },{ multiple: true } %> <%= course_form.label :practical_instructor_IDs %><br /> <%= course_form.select :practical_instructor_IDs,{ multiple: true } %> <%= course_form.submit %><% end%>
问题是:为了使@course = Course.new(params [:course])能够在课程控制器中唯一的代码行在提交上一个表单时保存这个关联,我能做些什么?
与this question不同,我不想在创建新课程时创建新的Trainer对象:我想从已经存在于DB中的那些(通过多选输入字段)中选择它们.
我需要的是像@ course.theoretical_instructor_IDs = [1,2]之类的东西创建两个Training对象,其role属性设置为Theory Instructor
我正在考虑关于训练的after_initialize回调,它基于关系名称(:theoretical_instructors和:practical_instructors)设置角色,但我真的不知道该怎么做.有什么建议?我错过了一些观点吗?
感谢你们!
来自oli-g的编辑1
This question处理类似的问题:区别在于我不想在创建新课程时构建Trainer对象,但我只想将现有的Trainer对象与新课程相关联.
编辑2来自oli-g
基于this(5岁的帖子)和this博客文章,我以这种方式更改了课程模型:
class Course < ActiveRecord::Base has_many :trainings,conditions: ["trainings.role = ?","Theoretical Instructor"] do def <<(theoretical_instructor) Training.send(:with_scope,create: { role: "Theoretical Instructor" }) { self.concat theoretical_instructor } end end accepts_nested_attributes_for :theoretical_instructors has_many :practical_instructors,"Practical Instructor"] do def <<(practical_instructor) Training.send(:with_scope,create: { role: "Practical Instructor" }) { self.concat practical_instructor } end end accepts_nested_attributes_for :practical_instructorsend
这段代码让我可以做这样的事情
:001 > c = Course.first=> #<Course ID: 1>:002 > t1 = Trainer.first=> #<Trainer ID: 1,name: "Tom">:003 > c.theoretical_instructors << t1=> #<Trainer ID: 1,name: "Tom">:004 > Training.all=> [#<Training ID: 1,role: "Theoretical Instructor",trainer_ID: 1,course_ID: 1>]
这是一个可接受的解决方法,即使在我的控制器中我仍然不能只做@course = Course.new(params [:course]),但我必须创建训练对象迭代params [:course] [:theoretical_instructor_IDs]和params [:course] [:practical_instructor_IDs].
但我很好奇,所以问题仍然存在:为了使@course = Course.new(params [:course])能够与课程一起构建训练对象,我能做些什么?
现在……我想我在Rails中发现了一个错误:
:005 > c.practical_instructors=> [] # correct:006 > c.practical_instructor_IDs=> [] # obvIoUsly:007 > c.reload=> #<Course ID: 1>:008 > c.practical_instructor_IDs=> [1] # WRONG!!!:009 > c.practical_instructors=> [] # Now it's correct...:010 > c.practical_instructor_IDs=> [] # WTF!?
我想我会在github问题上报告这个……
编辑3由oli-g
BUG报道于github
解决方法 您的问题是,在创建记录之前,您将无法添加关联.在这种情况下,使用课程记录ID存储培训关联,并且直到首次保存课程之后才定义课程ID.您要做的是在创建记录后使用after_create回调来调用函数.将其添加到课程模型的末尾:
# Use attr accessors to store the initial values so they won't conflict with the *_instructor_IDs methods defined above attr_accessor :create_theoretical_instructorsattr_accessor :create_practical_instructors# This will call the create_training_records function after the record is createdafter_create :create_training_recordsprivatedef create_training_records create_theoretical_instructors.each do |instructor_ID| self.theoretical_instructors << Instructor.find(instructor_ID) end create_practical_instructors.each do |instructor_ID| self.practical_instructors << Instructor.find(instructor_ID) end save!end
并在视图中更改表单以使用新的attr_accessors:
<%= course_form.label :create_theoretical_instructors %><br /><%= course_form.select :create_theoretical_instructors,{ multiple: true } %><%= course_form.label :create_practical_instructors %><br /><%= course_form.select :create_practical_instructors,{ multiple: true } %>
现在,当您提交表单时,它会将指导者ID写入新的Course实例变量;在课程经过验证和保存后,它将自动创建新的关联.
总结以上是内存溢出为你收集整理的ruby-on-rails-3 – Rails 3和has_many:through:在连接模型上自动设置/初始化属性全部内容,希望文章能够帮你解决ruby-on-rails-3 – Rails 3和has_many:through:在连接模型上自动设置/初始化属性所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)