【发布时间】:2017-03-17 20:12:55
【问题描述】:
我正在使用reform-rails gem 以便在我的rails 项目中使用表单对象。
我意识到表单对象对于我在下面使用的示例代码来说可能是多余的,但它是出于演示目的。
在我创建user 的表单中,与该用户记录相关联的是两个user_emails。
# models/user.rb
class User < ApplicationRecord
has_many :user_emails
end
# models/user_email.rb
class UserEmail < ApplicationRecord
belongs_to :user
end
请注意,我没有在 User 模型中使用 accepts_nested_attributes_for :user_emails。在我看来,表单对象的要点之一是它可以帮助您摆脱使用accepts_nested_attributes_for,所以这就是我试图在没有它的情况下这样做的原因。我从this video 那里得到了这个想法,它谈到了重构胖模型。我有指向视频中关于表单对象部分的链接,他表达了他多么不喜欢accepts_nested_attributes_for。
然后我继续创建我的user_form:
# app/forms/user_form.rb
class UserForm < Reform::Form
property :name
validates :name, presence: true
collection :user_emails do
property :email_text
validates :email_text, presence: true
end
end
所以user_form 对象包装了一个user 记录,然后是几个与该user 记录关联的user_email 记录。在user 和user_email 记录上有表单级验证,此表单包含:
-
user#name必须有一个值 - 每个
user_email#email_text都必须有一个值
如果表单是有效的:那么它应该创建一个user 记录,然后是一对关联的user_email 记录。如果表单无效:那么它应该重新呈现带有错误消息的表单。
我将展示到目前为止我在控制器中拥有的东西。为简洁起见:仅显示new 操作和create 操作:
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
user = User.new
user.user_emails.build
user.user_emails.build
@user_form = UserForm.new(user)
end
def create
@user_form = UserForm.new(User.new(user_params))
if @user_form.valid?
@user_form.save
redirect_to users_path, notice: 'User was successfully created.'
else
render :new
end
end
private
def user_params
params.require(:user).permit(:name, user_emails_attributes: [:_destroy, :id, :email_text])
end
end
最后:表单本身:
# app/views/users/_form.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>
<% f.fields_for :user_emails do |email_form| %>
<div class="field">
<%= email_form.label :email_text %>
<%= email_form.text_field :email_text %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
作为测试:这是输入值的表单:
现在我继续提交。应该发生的是应该存在验证错误,因为必须存在第二封电子邮件的值。但是,在这里提交时是日志:
Parameters: {"utf8"=>"✓", "authenticity_token"=>”123abc==", "user"=>{"name"=>"neil", "user_emails_attributes"=>{"0"=>{"email_text"=>"email_test1"}, "1"=>{"email_text"=>""}}}, "commit"=>"Create User"}
ActiveModel::UnknownAttributeError (unknown attribute 'user_emails_attributes' for User.):
所以我的表单对象有一些问题。
我怎样才能让这个表单对象工作?是否可以使用reform_rails 并使用accepts_nested_attributes 让这个表单对象工作?最终:我只想让表单对象工作。
除了reform-rails 文档之外,我已经探索过一些资源:
我第一次尝试创建表单对象是使用virtus gem,但我似乎也无法让那个对象工作。我也为该实现发布了stackoverflow question。
【问题讨论】:
-
您可能想检查在它们从未被持久化的情况下,Reform 如何处理来自参数的集合对象的实例化和验证。例如,
accepts_nested_attributes_for具有拒绝空白的选项。
标签: ruby-on-rails ruby reform