Ruby on rails 在Rails中形成对象
下面的示例代码是一个故意尝试使用表单对象的示例,在这种情况下,使用表单对象可能会有过大的杀伤力。尽管如此:它显示了我面临的问题: 我有两种型号:一个Ruby on rails 在Rails中形成对象,ruby-on-rails,ruby,Ruby On Rails,Ruby,下面的示例代码是一个故意尝试使用表单对象的示例,在这种情况下,使用表单对象可能会有过大的杀伤力。尽管如此:它显示了我面临的问题: 我有两种型号:一个用户和一个电子邮件: # app/models/user.rb class User < ApplicationRecord has_many :emails end 注意:表单对象上的验证。如果用户表单的名称属性为空,或者如果电子邮件表单数组中的任何电子邮件表单对象的电子邮件文本属性为空,则认为该表单无效 为简洁起见:我将仅介绍使用用
用户
和一个电子邮件
:
# app/models/user.rb
class User < ApplicationRecord
has_many :emails
end
注意:表单对象上的验证。如果
用户表单
的名称
属性为空,或者如果电子邮件表单
数组中的任何电子邮件表单
对象的电子邮件文本
属性为空,则认为该表单无效
为简洁起见:我将仅介绍使用用户表单的新建
和创建
操作:
# 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
应该发生的是表单应该被重新呈现,并且没有任何内容被持久化,因为form_对象无效:所有三封关联的电子邮件都不能为空。但是:form_对象认为它是有效的,它在persist中爆炸UserForm
上的code>方法。它突出显示Email.create(用户:用户,Email\u文本:Email.Email\u文本)
行,并显示:
[“0”,{“email\u text”=>“test\u email\u 1}]:数组的未定义方法“email\u text”
很明显,有两件事正在发生:嵌套的验证似乎不起作用,而且我在从params散列重新生成每个电子邮件时遇到困难
我已经检查过的资源:
#app/models/user.rb
class User < ApplicationRecord
has_many :emails
end
#app/models/email.rb
class Email < ApplicationRecord
belongs_to :user
end
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
@users = User.all
end
def new
@user_form = UserForm.new
@user_form.emails = [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, {emails_attributes: [:email_text]})
end
end
#app/forms/user_form.rb
class UserForm
include ActiveModel::Model
attr_accessor :name, :emails
validates :name, presence: true
validate :all_emails_valid
def emails_attributes=(attributes)
@emails ||= []
attributes.each do |_int, email_params|
email = EmailForm.new(email_params)
@emails.push(email)
end
end
def save
if valid?
persist!
true
else
false
end
end
private
def persist!
user = User.new(name: name)
new_emails = emails.map do |email_form|
Email.new(email_text: email_form.email_text)
end
user.emails = new_emails
user.save!
end
def all_emails_valid
emails.each do |email_form|
errors.add(:base, "Email Must Be Present") unless email_form.valid?
end
throw(:abort) if errors.any?
end
end
app/forms/email_form.rb
class EmailForm
include ActiveModel::Model
attr_accessor :email_text, :user_id
validates :email_text, presence: true
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>
<%= f.fields_for :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 %>
- 看起来很有希望,但我很难让它发挥作用
- 我已经尝试了使用virtus gem和reform rails gem的实现。我还为这两个实现发布了悬而未决的问题:然后
- 我曾尝试插入
接受嵌套的属性,但在弄清楚如何利用表单对象和嵌套表单对象(如本代码示例中)时遇到了问题。问题的一部分是有许多
和接受
的嵌套属性似乎没有包含在ActiveModel::Model
中
非常感谢您提供有关如何让此表单对象执行预期操作的任何指导!谢谢 完整答案
型号:
#app/models/user.rb
class User < ApplicationRecord
has_many :emails
end
#app/models/email.rb
class Email < ApplicationRecord
belongs_to :user
end
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
@users = User.all
end
def new
@user_form = UserForm.new
@user_form.emails = [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, {emails_attributes: [:email_text]})
end
end
#app/forms/user_form.rb
class UserForm
include ActiveModel::Model
attr_accessor :name, :emails
validates :name, presence: true
validate :all_emails_valid
def emails_attributes=(attributes)
@emails ||= []
attributes.each do |_int, email_params|
email = EmailForm.new(email_params)
@emails.push(email)
end
end
def save
if valid?
persist!
true
else
false
end
end
private
def persist!
user = User.new(name: name)
new_emails = emails.map do |email_form|
Email.new(email_text: email_form.email_text)
end
user.emails = new_emails
user.save!
end
def all_emails_valid
emails.each do |email_form|
errors.add(:base, "Email Must Be Present") unless email_form.valid?
end
throw(:abort) if errors.any?
end
end
app/forms/email_form.rb
class EmailForm
include ActiveModel::Model
attr_accessor :email_text, :user_id
validates :email_text, presence: true
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>
<%= f.fields_for :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 %>
视图:
#app/models/user.rb
class User < ApplicationRecord
has_many :emails
end
#app/models/email.rb
class Email < ApplicationRecord
belongs_to :user
end
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
@users = User.all
end
def new
@user_form = UserForm.new
@user_form.emails = [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, {emails_attributes: [:email_text]})
end
end
#app/forms/user_form.rb
class UserForm
include ActiveModel::Model
attr_accessor :name, :emails
validates :name, presence: true
validate :all_emails_valid
def emails_attributes=(attributes)
@emails ||= []
attributes.each do |_int, email_params|
email = EmailForm.new(email_params)
@emails.push(email)
end
end
def save
if valid?
persist!
true
else
false
end
end
private
def persist!
user = User.new(name: name)
new_emails = emails.map do |email_form|
Email.new(email_text: email_form.email_text)
end
user.emails = new_emails
user.save!
end
def all_emails_valid
emails.each do |email_form|
errors.add(:base, "Email Must Be Present") unless email_form.valid?
end
throw(:abort) if errors.any?
end
end
app/forms/email_form.rb
class EmailForm
include ActiveModel::Model
attr_accessor :email_text, :user_id
validates :email_text, presence: true
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>
<%= f.fields_for :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 %>
app/views/users/new.html.erb
新用户
#app/views/users/_form.html.erb
禁止保存此用户:
您是否查看了“”的接受嵌套属性。。。这加上gemcocoon
基本上消除了处理嵌套属性的所有困难。@SteveTurczyn是的,我已经看过了为接受嵌套属性。我在弄清楚如何在表单对象中为
实现accepts\u nested\u attributes\u时遇到了很多麻烦。我更新了我的问题,表达了对这条路线的尝试。说真的,看看“茧”。这让一切变得容易。如果您在实现“cocoon”时遇到问题,请使用标签RubyonRails
和cocoon gem
发布问题,gem就在这里。。。我有同样的问题,用户模型有一个关联的模型地址。如果地址记录是否为空,如何设计formobject。如果地址记录为空,则应呈现地址字段,否则不应显示。