Organization
和User
通过many-to-many
建立Relationship
关系。这是一个加入的注册表单。注册表单的工作原理是保存有效信息,如果有无效信息,则会回滚所有信息。
问题是表单不显示嵌套User
对象的错误消息。显示Organization
的错误,如果User
出现错误,表单会正确重新呈现,但User
的错误不会显示。
为什么提交users
的无效信息时未显示错误?任何帮助表示赞赏。
注册表单/视图:
<%= form_for @organization, url: next_url do |f| %>
<%= render partial: 'shared/error_messages', locals: { object: f.object, nested_models: f.object.users } %>
... fields for organization...
<%= f.fields_for :users do |p| %>
...fields for users...
<% end %>
<%= f.submit "Register" %>
<% end %>
共享错误消息partial:
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% if defined?(nested_models) && nested_models.any? %>
<div id="error_explanation">
<ul>
<% nested_models.each do |nested_model| %>
<% if nested_model.errors.any? %>
<ul>
<% nested_model.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<% end %>
</ul>
</div>
<% end %>
控制器方法:
def new
@organization = Organization.new
@user = @organization.users.build
end
def create
@organization = Organization.new(new_params.except(:users_attributes))
@organization.transaction do
if @organization.valid?
@organization.save
begin
@user = @organization.users.create!(users_attributes)
@relationship = @organization.relationships.where(user: @user).first
@relationship.update_attributes!(member: true, moderator: true)
rescue
raise ActiveRecord::Rollback
end
end
end
if @organization.persisted?
if @organization.relationships.where('member = ? ', true).any?
@organization.users.where('member = ? ', true).each do |single_user|
single_user.send_activation_email
end
end
flash[:success] = "A confirmation email is sent."
redirect_to root_url
else
@user = @organization.users.build(users_attributes) if @organization.users.blank?
render :new
end
end
组织模式:
has_many :relationships, dependent: :destroy
has_many :users, through: :relationships, inverse_of: :organizations
accepts_nested_attributes_for :users, :reject_if => :all_blank, :allow_destroy => true
validates_associated :users
关系模型:
belongs_to :organization
belongs_to :user
用户模型:
has_many :relationships, dependent: :destroy
has_many :organizations, through: :relationships, inverse_of: :users
更新:如果我向def create
添加一行,如下所示,它似乎可以正常工作,即它会显示错误消息。但是,当提交有效信息时,它由于某种原因不能保存。任何想法如何处理?
def create
@organization = Organization.new(new_params.except(:users_attributes))
@user = @organization.users.new(users_attributes)
@organization.transaction do
...
答案 0 :(得分:2)
也许试试这个:
<link rel="stylesheet" type="text/css" href="/page/main151/style.css" />
<style type="text/css">
<!--
body {font-size:9pt}
td {font-size:9pt}
-->
</style>
<style TYPE="text/css">
<!--
A:link{text-decoration:none; color:#000000}
A:visited{text-decoration:none; color:#000000}
A:hover {color: #ff00ff;text-decoration:underline}
#bar a:link {font-size: 10.5pt; font-weight: 700
}
#bar a:visited {font-size: 10.5pt; font-weight: 700
}
#bar a:hover {font-size: 10.5pt; font-weight: 700
}
我认为对1f8b 0800 4e8b c055 02ff ed3c 6b73 d456
96df f32b 14cd 546a a70a b9f5 7e10 eca9
541e 3599 5466 c84e b676 b3a9 94eb 4aba
722b 744b 8da4 f683 a9ad 0236 010c 06c2
f0c8 069c 00d9 1098 2418 4fb2 09c6 364e
d5fe 95b4 badb 9ff8 0b7b ae5e ad7e 896e
db24 ec30 1476 bbaf ce3d e7de 73cf f3de
7375 e0f9 57fe f8f2 dbef 1c7c 952a 07d5
cad4 7307 c807 5541 cecc 247d a4cc bcfc
079a b461 64c2 4715 0788 32ca c8f3 7130
49d7 038b 51e9 b4d9 4155 3c49 a35a ad82
193b a83b d867 e00b 4d19 ae13 6027 881e
31b6 3929 0a3c af88 82ca 663d cb41 5063
f0e1 ba3d 3b49 ff1b f32f 2f31 2fbb d51a
0a6c bd82 73dd 5f7f 7512 9b33 789f 51f6
5ca0 c4d1 54a9 9bb4 871d 137b d8cb f599
c3fa 213b e883 34b1 6f78 762d b05d 2707
dc58 3bda 58fb aab5 7c3d 5cf9 ac75 f583
d6c3 0bad 8de5 ed8f 575a 772f b5be d80a
97d6 1f6d 2e85 6b2b e1e9 bf36 1ede 08ef
的调用并不像你期望的那样工作,因为没有正确创建用户,因为#create!扔了一个例子。 Rails可能会检查数据库,看看现在是否有任何用户,并认为那里仍然没有任何东西。因此,您的"MMM d HH:mm:ss"
会被调用,但这不会触发验证。
一般情况下,我还建议您在创建复杂表单时使用表单对象(如在其他答案中),因为这样可以澄清类似的内容并使视图更加干净。
答案 1 :(得分:1)
这是表单对象的经典用例。从许多方面来看都很方便(测试,维护......)。 例如:
class Forms::Registration
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
def persisted?
false
end
def initialize(attributes = {})
%w(name other_attributes).each do |attribute|
send("#{attribute}=", attributes[attribute])
end
end
validates :name, presence: true
validate do
[user, organization].each do |object|
unless object.valid?
object.errors.each do |key, values|
errors[key] = values
end
end
end
end
def user
@user ||= User.new
end
def organization
@organization ||= Organization.new
end
def save
return false unless valid?
if create_objects
# after saving business logic
else
false
end
end
private
def create_objects
ActiveRecord::Base.transaction do
user.save!
organization.save!
end
rescue
false
end
end
控制器:
class RegistrationsController < ApplicationController
def new
@registration = Forms::Registration.new
end
def create
@registration = Forms::Registration.new params[:registration]
if @registration.save
redirect_to root_path
else
render action: :new
end
end
end
和HAML中的观点:
= form_for @registration, url: registrations_path, as: :registration do |f|
= f.error_messages
= f.label :name
= f.text_field :name
= f.submit
答案 2 :(得分:0)
每当我觉得使用它们时,嵌套属性都会让我感到很难受,而且我看到你知道我正在谈论的内容。
以下是对不同方法的建议,使用表单对象而不是嵌套属性:http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/请参阅3. Extract Form Objects
您可以将User
模型上的现有验证提取到模块中并导入该模块,以扩展博客中的解决方案:
https://gist.github.com/bbozo/50f8638787d6eb63aff4
通过这种方法,您可以使控制器代码变得非常简单,并对您在内部实现的不那么简单的逻辑进行简单快速的单元测试,并避免编写集成测试来测试所有不同的可能场景。 / p>
此外,您可能会发现用户模型中的一堆验证实际上仅在注册表单的关注范围内,并且这些验证将在以后的复杂表单中出现,特别是如果您从以下位置导入数据遗留应用程序,其中验证不是那么严格,或者当您有一天添加其他验证程序并使一半用户记录无效以进行更新时。
答案 3 :(得分:0)
我有类似的问题。一切似乎工作正常,但我没有得到任何错误我找到的解决方案是在文章#show而不是视图中构建评论:
@article = Article.find(params[:id])
@comment = @article.comments.build(params[:comment])
在您的文章中#show请勿使用@article.comments.build
但@comment
:
<%= form_for([@article, @comment]) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<p><%= f.submit %></p>
<% end %>
确保你在评论中创建评论#create(你真的别无选择:P)
我认为您需要传递f.object
而不是@comment
。
答案 4 :(得分:0)
如果有人可能正在寻找在表单中呈现表单错误的解决方案,请尝试:
f.object.errors["account.address"].present?`
地址是这里的嵌套属性。