我认为最好的方法是创建一个新模型来表示 Team 和 MiniLeague 之间的联系。
事实上,需要验证的是这种联系。另外,我猜至少理论上一个团队可以被放弃/被逐出迷你联赛;在这种情况下,您要破坏的是两个模型之间的连接。
假设采用这种方法,您可以使用新模型中的自定义验证器检查密钥。
所以,如果我们调用新模型,让我们说 Enrollment:
在 app/models/team.rb 中:
class Team < ActiveRecord::Base
attr_accessible :team_name, :user_id, :key
belongs_to :user
has_many :mini_leagues, through: enrollments
end
在 app/models/mini_league.rb 中:
class MiniLeague < ActiveRecord::Base
attr_accessible :league_name, :league_key
has_many :teams, through: enrollments
end
在 app/models/enrollment.rb 中:
class Enrollment < ActiveRecord::Base
attr_accessible :team_id, :mini_league_id
belongs_to :team
belongs_to :mini_league
validate :valid_key?
protected
def valid_key?
errors.add(:base, "Invalid key") unless team.key == mini_league.league_key
end
end
现在,注册控制器将负责创建团队和迷你联赛之间的连接,而不是团队控制器。
所以你的控制器只负责触发“保存”方法,这取决于模型逻辑是有效还是无效,因为它应该是(app/controllers/enrollments_controller.rb):
class EnrollmentsController < ApplicationController
...
def create
@enrollemnt = Enrollment.new(params[:enrollment])
if @enrollment.save
# success, go on with the application flow
else
# error, automanaged for custom model validator if comes from a non valid league key, show the form again
render :new
end
end
end
现在,如果您想显示我们在自定义验证器中创建的自定义错误消息,简单的方法是创建要插入到新团队表单中的部分:
在您的 app/views/enrollments/_form.html.erb 中:
<%= form_for(@enrollment) do |f| %>
<%= render "shared/error_messages", :target => @enrollment %>
# and then the rest of your form
...
在 app/views/shared/error_messages 中:
<% if target.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(target.errors.count, "error") %> prohibited this record from being saved:</h2>
<ul>
<% target.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
target.errors 包含错误数组,包括我们的自定义验证器之一,并且通过 full_messages 集合的迭代将显示“无效密钥”消息。
总结一下
创建新注册后,相关团队和小联盟都会响应:
my_team.mini_leagues
并
my_mini_league.teams