Просмотры:
денный ниже пример кода является надуманным примером попытки использования объекта формы, когда, вероятно, излишне использовать объект формы. Тем не менее: это показывает проблему, которую я имею:
У меня есть две модели: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
.Будем очень благодарны за любые рекомендации, как заставить этот объект формы делать то, что ожидается. Спасибо!