两个模型,组织和用户,有1:多关系。我有一个组合注册表单,组织和该组织的用户都可以注册。
我遇到的问题是:当为用户提交无效信息时,它会再次呈现表单,但是用户的错误消息(例如“用户名不能为空”)不是显示。表单在提交有效信息时确实有效,并且确实显示组织的错误消息,而不是用户。
我应该如何调整下面的代码,以便显示用户的错误消息?
def new
@organization = Organization.new
@user = @organization.users.build
end
def create
@organization = Organization.new(new_params.except(:users_attributes)) #Validations require the organization to be saved before user, since user requires an organization_id. That's why users_attributs are above excluded and why below it's managed in a transaction that rollbacks if either organization or user is invalid. This works as desired.
@organization.transaction do
if @organization.valid?
@organization.save
begin
# I executed next line in debugger (with invalid user info), which correctly responds with: ActiveRecord::RecordInvalid Exception: Validation failed: Email can't be blank, Email is invalid, Username can't be blank, etc.
@organization.users.create!(users_attributes)
rescue
# Should I perhaps add some line here that adds the users errors to the memory?
raise ActiveRecord::Rollback
end
end
end
if @organization.persisted?
flash[:success] = "Yeah!"
redirect_to root_url
else
@user = @organization.users.build(users_attributes) # Otherwise the filled in information for user is gone (fields for user are then empty)
render :new
end
end
表单视图包括:
<%= form_for @organization, url: next_url do |f| %>
<%= render partial: 'shared/error_messages', locals: { object: f.object, nested_models: f.object.users } %>
<%= f.text_field :name %>
# Other fields
<%= f.fields_for :users do |p| %>
<%= p.email_field :email %>
# Other fields
<% end %>
<%= f.submit "Submit" %>
<% end %>
错误消息部分如下:
<% object.errors.full_messages.each do |msg| %>
<li><%= msg.html_safe %></li>
<% end %>
更新:按照Rob的回答,我到达了下面的错误部分。这仍然不会显示用户的错误消息。我在下面的代码中添加了调试器响应,由于某种原因nested_model.errors.any?
返回false,而控制器内的调试器(见上文)确实为用户返回错误消息。
<% 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.html_safe %></li>
<% end %>
</ul>
</div>
<% end %>
<% if defined?(nested_models) && nested_models.any? %>
# Debugger: responds with "local-variable" for "defined?(nested_models)" and for "nested_models.any?" returns true.
<div id="error_explanation">
<ul>
<% nested_models.each do |nested_model| %>
# Debugger: "nested_model" has the same values as "nested_models.any?", as you would expect. But for "nested_model.errors.any?" it returns false, which it shouldn't.
<% if nested_model.errors.any? %> #Initially had "unless nested_model.valid?" but then errors for User are immediately displayed on loading the form page (new method).
<ul>
<% nested_model.errors.full_messages.each do |msg| %>
<li><%= msg.html_safe %></li>
<% end %>
</ul>
<% end %>
<% end %>
</ul>
</div>
<% end %>
答案 0 :(得分:0)
尝试在您的validates_associated :users
协会组织下添加has_many :users
。
http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_associated
答案 1 :(得分:0)
您是否在救援区段内成功创建了一个人?
rescue ActiveRecord::RecordInvalid => exception
# do something with exception here
raise ActiveRecord::Rollback
@organization.users.build if @organization.users.blank?
render :new and return
此代码看起来会创建一个新的空用户,无论验证不正确。假设组织没有用户,则渲染new将简单地返回没有错误,因为用户已成功创建。
这种方法的控制流程有一些结果,肯定需要进一步细分。我会使用byebug并使用不正确的组织遍历块,然后使用错误的名称。然后是一个空组织,其用户属性不正确。
答案 2 :(得分:0)
组织has_many:用户和用户belongs_to:organization
organization.rb
accepts_nested_attributes_for :users
new.html.erb
<%= form_for @organization, url: next_url do |f| %>
<%= render 'shared/error_messages', object: @organization %>
<%= f.text_field :name %>
# Other fields
<%= f.fields_for(:users,@organization.users.build) do |p| %>
<%= p.email_field :email %>
# Other fields
<% end %>
<%= f.submit "Submit" %>
<% end %>
在控制器中
def create
@organization = Organization.new(new_params)
if @organization.save
flash[:success] = "Yeah!"
redirect_to root_url
else
render :new
end
end
答案 3 :(得分:0)
这与this question非常相关。关键是我假设<%= render 'shared/error_messages', object: f.object %>
仅在传递的对象上调用.errors
方法(在本例中为organization
)。
但是,由于user
错误存在于user
对象中,因此无法返回,因此不会显示。这需要简单地更改视图逻辑,以便在各种.errors
模型上显示user
的结果。你想怎么做取决于你。在链接的线程中,接受的答案有错误消息显示代码内联而不是部分,所以你可以这样做,但它会有点多余。
我会修改我的shared/error_messages.html.erb
文件以检查另一个名为nested_models
的传递本地文件。然后它将使用它来搜索关联的模型并在其上包含错误。我们只需要检查它是否是第一个定义的,这样你的其他不具有嵌套模型的视图就不会导致它引发错误。
<强>共享/ error_messages.html.erb 强>
<% if object.errors.any? %>
<div class="error-messages">
Object Errors:
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% if defined?(nested_models) && nested_models.any? %>
Nested Model(s) Errors:
<ul>
<% nested_models.each do |nested_model| %>
<% unless nested_model.valid? %>
<li>
<ul>
<% nested_model.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</li>
<% end %>
<% end %>
</ul>
<% end %>
</div>
<% end %>
然后您只需要在视图中更改一行:
<%= render partial: 'shared/error_messages', locals: { object: @organization, nested_models: @organization.users } %>
答案 4 :(得分:0)
看起来你的控制器中有很多不可测试的逻辑。看起来对你来说逻辑会更好用到简单的FormObject模式。 https://robots.thoughtbot.com/activemodel-form-objects