Просмотры:

денный ниже пример кода является надуманным примером попытки использования объекта формы, когда, вероятно, излишне использовать объект формы. Тем не менее: это показывает проблему, которую я имею:

У меня есть две модели:User иEmail:

# app/models/user.rb
class User < ApplicationRecord
  has_many :emails
end
# app/models/user.rb
class Email < ApplicationRecord
  belongs_to :user
end

Я хочу создатьобъект формы который создаетuser запись, а затем создает три связанныхemail записей.

Вот мои классы объектов формы:

# app/forms/user_form.rb
class UserForm 
  include ActiveModel::Model

  attr_accessor :name, :email_forms

  validates :name, presence: true

  def save
    if valid?
      persist!
      true
    else
      false
    end
  end

  private

  def persist!
    puts "The Form is VALID!"
    puts "I would proceed to create all the necessary objects by hand"

    user = User.create(name: name)
    email_forms.each do |email|
      Email.create(user: user, email_text: email.email_text)
    end
  end
end
# app/forms/email_form.rb
class EmailForm 
  include ActiveModel::Model

  attr_accessor :email_text, :user_id

  validates :email_text, presence: true

  def save
    if valid?
      persist!
      true
    else
      false
    end
  end

  private

  def persist!
    puts "The Form is VALID!"
    # DON'T THINK I WOULD PERSIST DATA HERE
    # INSTEAD DO IT IN THE user_form
  end
end

уведомление:проверки на объектах формы,user_form считается недействительным, если этоname атрибут пуст, или еслиemail_text атрибут остается пустым для любого изemail_form объекты внутри этоemail_forms массив.

Для краткости: я просто буду проходить черезnew а такжеcreate действие использованияuser_form:

# app/controllers/user_controller.rb
class UsersController < ApplicationController

  def new
    @user_form = UserForm.new
    @user_form.email_forms = [EmailForm.new, EmailForm.new, EmailForm.new]
  end

  def create
    @user_form = UserForm.new(user_form_params)

    if @user_form.save
      redirect_to users_path, notice: 'User was successfully created.' 
    else
      render :new
    end 
  end

  private

  def user_form_params
    params.require(:user_form).permit(:name, {email_forms: [:_destroy, :id, :email_text, :user_id]})
  end
end

И наконец: сама форма:

# app/views/users/new.html.erb
<h1>New User</h1>

<%= render 'form', user_form: @user_form %>
<%= link_to 'Back', users_path %>
# app/views/users/_form.html.erb
<%= form_for(user_form, url: users_path) do |f| %>
  <% if user_form.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(user_form.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% user_form.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %>
    <%= f.text_field :name %>
  </div>

  # MESSY, but couldn't think of a better way to do this...
  <% unique_index = 0 %>
  <% user_form.email_forms.each do |email_form| %>
    <div class="field">
      <%= label_tag "user_form[email_forms][#{unique_index}][email_text]", "Email Text" %>
      <%= text_field_tag "user_form[email_forms][#{unique_index}][email_text]" %>
    </div>
    <% unique_index += 1 %>
  <% end %>


  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Форма отображает:

И вот HTML-код формы:

Я иду, чтобы отправить форму. Вот хэш параметров:

Parameters: {"utf8"=>"✓", "authenticity_token"=>”abc123==", "user_form"=>{"name"=>"neil", "email_forms"=>{"0"=>{"email_text"=>"test_email_1"}, "1"=>{"email_text"=>"test_email_2"}, "2"=>{"email_text"=>""}}}, "commit"=>"Create User form"}

Что должно произойти, так это то, что форма должна быть перерисована, и ничего не сохранилось, потому что form_object недействителен: все три связанных электронных письма НЕ должны быть пустыми. Тем не менее: form_object считает, что он действителен, и он взрывается вpersist! метод наUserForm, Это подчеркиваетEmail.create(user: user, email_text: email.email_text) строка и говорит:

неопределенный метод `email_text 'для [" 0 ", {" email_text "=>" test_email_1 "}]: массив

Очевидно, что происходит пара вещей: вложенные проверки, кажется, не работают, и у меня возникают проблемы при перестроении каждого письма из хэша params.

Ресурсы, которые я уже изучил:

Эта статья казалось многообещающим, но у меня были проблемы с тем, чтобы заставить его работать.Я попытался реализовать его с помощью камня добродетели и камня реформ. У меня есть еще вопросы, оставленные для обеих этих реализаций:попытка виртуса здесь а потомпопытка реформирования здесь.Я попытался подключитьaccepts_nested_attributes, но не мог понять, как использовать это с объектом формы, а также с вложенным объектом формы (как в этом примере кода). Часть проблемы заключалась в том, чтоhas_many а такжеaccepts_nested_attributes_for не включены вActiveModel::Model.

Будем очень благодарны за любые рекомендации, как заставить этот объект формы делать то, что ожидается. Спасибо!

Ответы на вопрос(1)

Ваш ответ на вопрос