我清理了我的代码,现在看起来好多了,但仍然无法正常工作。开始很痛苦……</p>
我只是无法以嵌套形式保存具有现有子级的父级与父级 has_many 子级:通过连接模型。
在我的例子中,一个项目 has_many 贡献的教师和许多贡献的学生,两者都是用户的加入模型。一个项目也有很多学校。
(也许我应该更好地将模型命名为 Teacherize 和 Pupilize 或 ProjectTeacher 和 ProjectPupil。)
只要所有记录都是新的,它就可以正常工作。一旦我想将现有用户连接为新项目的新教师,我就会收到以下错误:
Couldn't find User with ID=1 for Teacher with ID=
(1 是正确的用户 ID)
问题应该是她在我的助手中设置空表单字段的地方:
至少我猜是这样...
module ProjectsHelper
def setup_project(project)
if project.teachers.length <= 0 # usually there is just one teacher, so add one if there isn't one
teacher = project.teachers.build(:role_in_project => 'master')
if user_signed_in?
#teacher = project.teachers.new(:role_in_project => 'master', :user => current_user)
teacher.user = current_user # associate first teacher with current_user
else
#teacher = project.teachers.build
teacher.user = User.new # associate first teacher with a new user instance
end
end
if project.project_schools.length <= 0 # usually there is just one school, so add one if there isn't one
project_school = project.project_schools.build
project_school.school = School.new
end
if project.pupils.length < 3 # There can be up to 3 people, so add a blank fieldset as long as there are less than 3
pupil = project.pupils.build
pupil.user = User.new
end
project
end
end
这些是我收到的参数:
{"utf8"=>"✓", "authenticity_token"=>"uCCMk/s3SpDfR7+fXcsCOHPvfvivBQv8pVFVhdh6iro=",
"project"=>{
"teachers_attributes"=>{
"0"=>{
"id"=>"",
"user_attributes"=>{
"id"=>"1",
"gender"=>"male",
"title"=>"",
"firstname"=>"Firstname1",
"name"=>"Lastname1",
"faculty"=>"",
"fon"=>"",
"fax"=>""}
}
},
"id"=>"",
"title"=>"First Project",
"description"=>"This is a foo bar project!",
"presentation_type"=>"experimentell",
"note"=>""
},
"commit"=>"Register Project",
"action"=>"create",
"controller"=>"projects"
}
案例不是太抽象;必须有可能实现它。只是将新的父记录与现有的子记录连接起来!
在这篇非常好的文章中,确切地解释了这种情况: http: //rubysource.com/complex-rails-forms-with-nested-attributes
# app/helpers/form_helper
module FormHelper
def setup_user(user)
user.address ||= Address.new
(Interest.all - user.interests).each do |interest|
user.interest_users.build(:interest => interest)
end
user.interest_users.sort_by! {|x| x.interest.name }
user/tmp/clean-controllers.md.html
end
end
那里的兴趣是存在的,并通过interest_uesers 中的新记录连接起来。
为什么我在尝试做同样的事情时会收到错误消息?
project.teachers.build(:user => current_user)
我研究了几篇文章和演员表,但没有一篇将现有的孩子联系起来。 http://railscasts.com/episodes/196-nested-model-form-revised http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for http://api.rubyonrails.org/classes/ActiveRecord/ NestedAttributes/ClassMethods.html Rails 3.1+ 嵌套表单问题:无法批量分配受保护的属性
尝试使用 Accepts_nested_attributes_for 和 has_and_belongs_to_many 但未填充连接表
Quote: “accepts_nested_fields_for 用于创建和修改表单中的相关对象。它可用于填充连接表,这正是您想要做的。但是,对于 HABTM 关系,使用accepts_nested_fields_for 填充连接表是不可能的。”</p>
这就是我想做的!填充连接表! 它开始令人沮丧,我很乐意得到一些帮助!
我的模特
class Project < ActiveRecord::Base
attr_accessible :title, :description, :presentation_type, :note,
:project_schools_attributes, :schools_attributes, :teachers_attributes, :pupils_attributes,
:users_attributes
validates_presence_of :title
validates_presence_of :description
validates_presence_of :presentation_type
has_many :project_schools, :dependent => :destroy
accepts_nested_attributes_for :project_schools
has_many :schools, :through => :project_schools
#accepts_nested_attributes_for :schools, :reject_if => :all_blank
has_many :pupils, :dependent => :destroy
accepts_nested_attributes_for :pupils, :reject_if => :all_blank
has_many :users, :through => :pupils
has_many :teachers, :dependent => :destroy
accepts_nested_attributes_for :teachers, :reject_if => :all_blank
has_many :users, :through => :teachers
#accepts_nested_attributes_for :users, :reject_if => :all_blank
end
class ProjectSchool < ActiveRecord::Base
attr_accessible :role_in_project, :comment,
:school_attributes, :school_id, :project_id
belongs_to :school
accepts_nested_attributes_for :school
belongs_to :project
end
class School < ActiveRecord::Base
attr_accessible :email, :fax, :fon, :name, :place, :street, :type_of_school, :www, :zip
has_many :project_schools
has_many :projects, :through => :project_schools
has_many :users # in real live they are named teachers and pupils but in this case the association goes directly to a user_id, not to teacher/pupil model
validates_presence_of :name, :type_of_school, :street, :place, :zip, :fon
validates :email, :format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create }, :allow_blank => true
end
class Teacher < ActiveRecord::Base
attr_accessible :role_in_project, :user, :user_attributes, :project_id, :user_id
belongs_to :project
belongs_to :user
accepts_nested_attributes_for :user
serialize :role_in_project
end
class Pupil < ActiveRecord::Base
attr_accessible :classname, :user_attributes #, :project_id, :user_id
belongs_to :project
belongs_to :user
accepts_nested_attributes_for :user
end
class User < ActiveRecord::Base
serialize :roles
belongs_to :school
has_many :teachers
has_many :pupils
has_many :projects, :through => :teachers
has_many :projects, :through => :pupils
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :gender, :firstname, :name, :street, :place, :title, :faculty, :assignment,
:classname, :zip, :fon, :fax, :school_id, :roles,
:password, :added_by_user_id, :password_confirmation, :remember_me
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable#, :validatable
after_initialize :init
def init
# the default guest user
self.roles ||= ['default'] #will set the default value only if it's nil
end
end
我的控制器
class ProjectsController < ApplicationController
require 'axlsx'
before_filter :load_page, only: [:show, :index, :destroy]
def new
@project = Project.new
end
def create
@project = Project.new(params[:project])
respond_to do |format|
if @project.save
sign_in(:user, @project.teachers[0].user) unless user_signed_in?
# TODO: send mail
# save as excel file in dropbox
save_in_dropbox(@project)
format.html { redirect_to @project, notice: t('project.was_created') }
else
logger.debug @project.errors.inspect
format.html { render action: "new" }
end
end
end
end
项目/_form.html.haml
%h1
= t('project.register_headline')
= simple_form_for( setup_project(@project), :html => {:class => 'form-horizontal'} )do |f|
= f.error_notification
#teachers-wrapper.well
%span.jumpanchor#lehrkraft_anchor
%fieldset.form-inputs
= f.simple_fields_for :teachers do |teacher|
= render "teacher_fields", :f => teacher
.school-wrapper.well
%span.jumpanchor#schule_anchor
%h2
Informationen zur Schule
%fieldset.form-inputs
= f.simple_fields_for :project_schools do |project_school|
= render "school_fields", :f => project_school
.project-wrapper.well
%span.jumpanchor#projekt_anchor
%h2
Informationen zum Projekt der Schüler
%fieldset.form-inputs
= f.hidden_field :id
= f.input :title, :input_html => { :class => 'span6' }
= f.input :description, :input_html => { :class => 'span6', rows: 5 }
= f.input :presentation_type, collection: ['theoretisch', 'experimentell'], as: :radio_buttons, :class => 'controls-row', :input_html => { :class => 'inline' }
.clearfix
= f.input :note, :input_html => { :class => 'span6', rows: 3 }
.pupils-wrapper.well
%span.jumpanchor#schuler_anchor
%fieldset.form-inputs
= f.simple_fields_for :pupils do |pupil|
= render "pupil_fields", :f => pupil
projects/_teacher_fields.html.haml
= f.simple_fields_for :user do |user|
=# render "teacher_user_fields", :f => user
%h2
Betreuende Lehrkraft
- if user_signed_in?
= user.input :email, :disabled => true, :input_html => {:class => 'email_validation'}
- else
= user.input :email, :autofocus => true, :input_html => {:class => 'email_validation'}, :hint => 'Dies muß Ihre eigene E-Mailadresse sein!'
.details
=# user.hidden_field :id
= user.input :id
= user.input :gender, collection: [:female, :male]
= user.input :title
= user.input :firstname
= user.input :name
= user.input :faculty
= user.input :fon
= user.input :fax
它是带有 Ruby 1.9.3 的 Rails 3.2