Rails 3 - сохраните несколько моделей с внешними ключами одновременно - PullRequest
1 голос
/ 22 марта 2012

У меня есть модели Пользователь , Учитель , Учитель Образование . TeacherEducation принадлежит Teacher , Teacher принадлежит User .

Я использую вложенные атрибуты для сохранения всего через одну строку в моем контроллере user.save. Но я встретил то, что не могу решить. Я могу установить идентификатор для Учителя, но не могу дать идентификатор для TeacherEducation , прежде чем смогу сохранить Учитель .

Можно ли это исправить и продолжать использовать вложенные атрибуты в моих моделях?

class User < ActiveRecord::Base
  attr_accessor   :password                                                               
  attr_accessible :user_login,                                                           
                  :password,
                  :teacher_attributes
  has_one :teacher
  accepts_nested_attributes_for :teacher 
end

class Teacher < ActiveRecord::Base
    attr_accessible :teacher_last_name,
                    :teacher_first_name,
                    :teacher_middle_name,
                    :teacher_birthday,
                    :teacher_sex,
                    :teacher_category,
                    :teacher_education_attributes
  belongs_to :user 
  has_one :teacher_education
  accepts_nested_attributes_for :teacher_education

  validates :user_id,             
            :presence => true
end

class TeacherEducation < ActiveRecord::Base
    attr_accessible :teacher_education_university,
                    :teacher_education_year,
                    :teacher_education_graduation,
                    :teacher_education_speciality
  belongs_to :teacher

  validates :teacher_id,             
            :presence => true

  ...
end

Мой контроллер

class AdminsController < ApplicationController
 def create_teacher  
    user = User.new( params[:user] )      
    user.user_role = "teacher"   
    user.teacher.user_id = current_user.id    # Work                                            
    user.teacher.teacher_education.teacher_id = user.teacher.id # Doesn't work

    if user.save
    ...
    end
 end
end

Итак, user.teacher.teacher_education.teacher_id = user.teacher.id не работает.

UPD

Error

Teacher teacher education teacher can't be blank, Teacher user can't be blank

Просмотр - new_teacher.html.erb

<%= form_for @user, :url => create_teacher_url, :html => {:class => "form-horizontal"} do |f| %>
  <%= field_set_tag do %>
        <%= f.fields_for :teacher do |builder| %>
      <div class="control-group">
        <%= builder.label :teacher_last_name, "Фамилия", :class => "control-label" %>
        <div class="controls">
          <%= builder.text_field :teacher_last_name, :value => @teacher_last_name %>
        </div>
      </div>

      <div class="control-group">
        <%= builder.label :teacher_first_name, "Имя", :class => "control-label" %>
        <div class="controls">
          <%= builder.text_field :teacher_first_name, :value => @teacher_first_name %>
        </div>
      </div>

      <div class="control-group">
        <%= builder.label :teacher_middle_name, "Отчество", :class => "control-label" %>
        <div class="controls">
          <%= builder.text_field :teacher_middle_name, :value => @teacher_middle_name %>
        </div>
      </div>

      <div class="control-group">
        <%= builder.label :teacher_sex, "Пол", :class => "control-label" %>
        <div class="controls">
          <%= label_tag nil, nil, :class => "radio" do %>
            <%= builder.radio_button :teacher_sex, 'm', :checked => @user_sex_man %>
            Мужской
          <% end %>

          <%= label_tag nil, nil, :class => "radio" do %>
            <%= builder.radio_button :teacher_sex, 'w', :checked => @user_sex_woman %>
            Женский
          <% end %>
        </div> 
      </div>

      <div class="control-group">
        <%= builder.label :teacher_birthday, "Дата рождения", :class => "control-label" %>
        <div class="controls">
          <%= builder.text_field :teacher_birthday, :value => @teacher_birthday %>
          <p class="help-block">Формат даты: дд.мм.гггг</p>
        </div>
      </div>

      <div class="control-group">
        <%= builder.label :teacher_category, "Категория", :class => "control-label" %>
        <div class="controls">
          <%= builder.text_field :teacher_category, :value => @teacher_category %>
        </div>
      </div>

      <%= builder.fields_for :teacher_education do |edu_fields| %>
        <div class="control-group">
          <%= edu_fields.label :teacher_education_university, "Название ВУЗа", :class => "control-label" %>
          <div class="controls">
            <%= edu_fields.text_field :teacher_education_university, :value => @teacher_university %>
          </div>
        </div>

        <div class="control-group">
          <%= edu_fields.label :teacher_education_year, "Дата выпуска из ВУЗа", :class => "control-label" %>
          <div class="controls">
            <%= edu_fields.text_field :teacher_education_year, :value => @teacher_finish_univ %>
            <p class="help-block">Формат даты: дд.мм.гггг</p>
          </div>
        </div>

        <div class="control-group">
          <%= edu_fields.label :teacher_education_graduation, "Степень", :class => "control-label" %>
          <div class="controls">
            <%= edu_fields.text_field :teacher_education_graduation, :value => @teacher_graduation %>
          </div>
        </div>

        <div class="control-group">
          <%= edu_fields.label :teacher_education_speciality, "Специальность", :class => "control-label" %>
          <div class="controls">
            <%= edu_fields.text_field :teacher_education_speciality, :value => @teacher_specl %>
          </div>
        </div>
      <% end %>             
        <% end %>

      <hr/>

        <div class="control-group">
        <%= f.label :user_login, "Логин учетной записи", :class => "control-label" %>
        <div class="controls">
          <%= f.text_field :user_login, :value => @user_login %>
              <%= link_to_function "Сгенерировать логин", "generate_login()", :class => "btn" %>
        </div>
      </div>

      <div class="control-group">
        <%= f.label :password, "Пароль учетной записи", :class => "control-label" %>
        <div class="controls">
          <%= f.text_field :password, :value => @user_password  %>
                <%= link_to_function "Сгенерировать пароль", "generate_password()", :class => "btn" %>
        </div>
      </div>
    <% end %>

    <%= f.submit "Создать", :class => "btn btn-large btn-success" %>
<% end %>

Также, некоторая отладочная информация:

user: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  password: somepass
  teacher_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
    teacher_birthday: 21.12.1990
    teacher_category: categ
    teacher_education_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
      teacher_education_graduation: grad
      teacher_education_speciality: spec
      teacher_education_university: univ
      teacher_education_year: 28.09.2000
    teacher_first_name: name
    teacher_last_name: last
    teacher_middle_name: middle
    teacher_sex: w
  user_login: schoolh_Lyp1v
utf8: ✓
controller: admins

Моя схема

  create_table "teacher_educations", :force => true do |t|
    t.integer  "teacher_id"
    t.string   "teacher_education_university"
    t.date     "teacher_education_year"
    t.string   "teacher_education_graduation"
    t.string   "teacher_education_speciality"
    t.datetime "created_at",                   :null => false
    t.datetime "updated_at",                   :null => false
  end

  create_table "teacher_phones", :force => true do |t|
    t.integer  "teacher_id"
    t.string   "teacher_home_number"
    t.string   "teacher_mobile_number"
    t.datetime "created_at",            :null => false
    t.datetime "updated_at",            :null => false
  end

  create_table "teachers", :force => true do |t|
    t.integer  "user_id"
    t.string   "teacher_last_name"
    t.string   "teacher_first_name"
    t.string   "teacher_middle_name"
    t.date     "teacher_birthday"
    t.string   "teacher_sex"
    t.string   "teacher_category"
    t.datetime "created_at",          :null => false
    t.datetime "updated_at",          :null => false
  end

  create_table "users", :force => true do |t|
    t.string   "user_login"
    t.string   "user_role"
    t.datetime "created_at",         :null => false
    t.datetime "updated_at",         :null => false
    t.string   "encrypted_password"
    t.string   "salt"
  end

1 Ответ

1 голос
/ 22 марта 2012

Если вы правильно строите свою форму для поддержки вложенных атрибутов, то это все, что вам нужно:

user = User.new( params[:user] )
user.user_role = "teacher"     
if user.save
  ...
end

Механизм acceptpts_nested_attributes позаботится обо всем остальном.Если вышеперечисленное не работает, давайте посмотрим, как ваша форма составлена.

...