Сложная форма с Rails - PullRequest
       1

Сложная форма с Rails

0 голосов
/ 03 августа 2011

У меня есть форма, в которой я хочу создать родительскую запись и дочернюю запись одновременно. Для простого примера, скажем, это компания с первым сотрудником.

в моем контроллере я делаю что-то вроде:

def new
    @company = Company.new
    @company.employees.new
end

и, на мой взгляд, это:

<%= form_for(@company) do |form| %>

    <div>
        <%= form.label :name %>
        <%= form.text_field :name %>
    </div>

    <%= form.fields_for :employees do |employee_form| %>

        <div>
            <%= employee_form.label :name %>
            <%= employee_form.text_field :name %>
        </div>

    <% end %>

<% end %>

и снова в моем контроллере:

def create
    @company = Company.new(params[:company])
    @company.employees << Employee.new(params[:company][:employees_attributes]["0"])

    # save stuff
end

Вопрос 1:

Не удалось получить коллекцию сотрудников в компании, которая будет заполнена одним сотрудником, созданным в форме. Когда я посмотрел на параметры, я нашел материал [: employee_attributes] ["0"].

Что у меня работает, но есть ли более чистый способ сделать это?

Вопрос 2:

Если проверка не проходит для сотрудника, я получаю общее сообщение «Сотрудники недействительны» вместо сообщения «Требуется имя». Я понимаю, что звоню сохранить в коллекции, и rails делает все возможное, чтобы исправить ошибку проверки, но есть ли более чистый способ сделать это, чтобы я мог получить ошибки, специфичные для сотрудника?

Короче

Как я могу очистить это, чтобы связанные модели создавались автоматически из параметров, и чтобы я получал сообщения проверки для одного сотрудника.

Спасибо за внимание.

1 Ответ

0 голосов
/ 03 августа 2011

1) fields_for организует вложение атрибутов дочерних объектов в атрибуты родительских объектов в хэш params, который отправляется обратно в действие контроллера.Чтобы заставить Rails автоматически обновлять дочерние объекты, скажите родительской модели принять вложенные атрибуты, используя объявление accepts_nested_attributes_for .

2) Для каждого объекта ActiveRecord существует объект ошибок.Просмотрите список ошибок и отобразите сообщения.

Лучший способ добиться этого - создать вспомогательный метод и метод представления, который будет обрабатывать ошибки за вас.затем замените сгенерированные сообщения об ошибках в формах вызовом вашего метода render_error_messages.У вас есть весь код для этого уже в сгенерированных формах.Вам просто нужно реорганизовать этот код в частичное, создать помощника - который должен принимать массив имен моделей в качестве параметра, а затем делать то, что вы хотите с информацией.Отобразите частичное для каждой модели или создайте частичное, которое будет иметь дело с дочерними объектами, а также с родительским объектом.В общем, ваш вызов.

3) Измените новое действие, чтобы создать, а не создавайте новый дочерний объект, поэтому вместо

def new
    @company = Company.new
    @company.employees.new
end

сделайте это

def new
    @company = Company.new
    @company.employees.build
end

4)Посмотрите эти Railscasts, чтобы увидеть, как работает accepts_nested_attributes

http://railscasts.com/episodes/196-nested-model-form-part-1

и

http://railscasts.com/episodes/197-nested-model-form-part-2

Обновление

Так как вышеприведенная информация оставляет вас в связи с вашими вопросами.

1) Что у меня работает, но есть ли более чистый способ сделать это?

Вы исправили новое действие в соответствии с пунктом 3 выше, верно?Теперь ваше действие создания может выглядеть так:

def create
    @company = Company.new(params[:company])

    # save stuff
end

, что намного чище, поскольку оно вернулось к исходному сгенерированному действию создания.Вы можете не думать, что это большая часть обновления и, следовательно, не так уж и чище.Ну, в изоляции вы были бы правы.Но учтите, что вы можете добавить столько связей, сколько захотите, и добавить столько полей fields_for, сколько захотите, и вы можете превратить отношения user -> employee в has_many (я знаю, что вы этого не сделаете).Вы можете сделать все это, и ваши действия по созданию и обновлению останутся ТОЛЬКО ОДНЫМИ, и поэтому он чище.

2) , есть более чистый способ сделать это, чтобы я мог получить ошибки, специфичные для сотрудника? Учитывая мой ответ в пункте 2 выше, вы знаете, что есть объект ошибок как на объекте работника, так и на объекте пользователя, верно?Теперь вы также знаете, что можете обойти этот объект ошибок, чтобы получить правильные сообщения?Таким образом, вы могли бы сделать это

  <% if @user.employee.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.employee.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% @user.employee.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

Рискнув себя, я просто скажу, что вам следует реорганизовать код представления сообщений об ошибках в парциальный, который примет любой объект в качестве параметра, после чего вы можете вызвать егос любого ракурса, что позволяет вам изменять стиль и функциональность для всех ваших форм.

Надеюсь, что понятнее

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...