私は次のモデルを持っています:チーム、メンバー、割り当て、役割
チームモデルhas_manyメンバー。各メンバーには、割り当てを通じて_manyの役割があります。役割の割り当ては、キャプテンとランナーです。メンバーモデルを使用してdeviseとCanCanもインストールしました。
私がする必要があるのは、各チームが最大1人のキャプテンと5人のランナーを持つように制限することです。
私はこの例を見つけました、そしてそれはいくつかのカスタマイズの後でうまくいくように見えました、しかし更新('teams / 1 / members / 4 / edit')で。作成(「チーム/ 1 /メンバー/新規」)では機能しません。しかし、私の他の検証(validates:role_ids、:presence => true)は、更新と作成の両方で機能します。どんな助けでもいただければ幸いです。
更新:この例は私の問題に似ているように見えますが、アプリで機能させることができないようです。
問題の根本は、検証前および検証中にカウント(またはサイズ)がどのように実行されるかにあるようです。
例えば:
レコードを更新するとき...チームに何人のランナーがいるかを確認し、カウントを返します。(つまり5)次に、メンバーに追加する役割を選択すると、データベースから既知のカウント(つまり、5)を取得し、提案された変更(つまり、1)を追加して、検証チェックを実行します。(Team.find(self.team_id).members.runner.count> 5)これは6および6> 5の値を返すため正常に機能し、提案された更新は保存せずに失敗し、エラーが発生します。
しかし、チームに新しいメンバーを作成しようとすると...チームに何人のランナーがいるかを確認し、カウントを返します。(つまり5)次に、メンバーに追加する役割を選択すると、データベース(つまり、5)から既知のカウントを取得し、提案された変更を考慮せずに検証チェックを実行します。これは、5つの既知のランナーと5 = 5の値を返すため機能しません。したがって、提案された更新は成功し、新しいメンバーとロールはエラーなしでデータベースに保存されます。
メンバーモデル:
class Member < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :password, :password_confirmation, :remember_me
attr_accessible :age, :email, :first_name, :last_name, :sex, :shirt_size, :team_id, :assignments_attributes, :role_ids
belongs_to :team
has_many :assignments, :dependent => :destroy
has_many :roles, through: :assignments
accepts_nested_attributes_for :assignments
scope :runner, joins(:roles).where('roles.title = ?', "Runner")
scope :captain, joins(:roles).where('roles.title = ?', "Captain")
validate :validate_runner_count
validate :validate_captain_count
validates :role_ids, :presence => true
def validate_runner_count
if Team.find(self.team_id).members.runner.count > 5
errors.add(:role_id, 'Error - Max runner limit reached')
end
end
def validate_captain_count
if Team.find(self.team_id).members.captain.count > 1
errors.add(:role_id, 'Error - Max captain limit reached')
end
end
def has_role?(role_sym)
roles.any? { |r| r.title.underscore.to_sym == role_sym }
end
end
メンバーコントローラー:
class MembersController < ApplicationController
load_and_authorize_resource :team
load_and_authorize_resource :member, :through => :team
before_filter :get_team
before_filter :initialize_check_boxes, :only => [:create, :update]
def get_team
@team = Team.find(params[:team_id])
end
def index
respond_to do |format|
format.html # index.html.erb
format.json { render json: @members }
end
end
def show
respond_to do |format|
format.html # show.html.erb
format.json { render json: @member }
end
end
def new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @member }
end
end
def edit
end
def create
respond_to do |format|
if @member.save
format.html { redirect_to [@team, @member], notice: 'Member was successfully created.' }
format.json { render json: [@team, @member], status: :created, location: [@team, @member] }
else
format.html { render action: "new" }
format.json { render json: @member.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @member.update_attributes(params[:member])
format.html { redirect_to [@team, @member], notice: 'Member was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @member.errors, status: :unprocessable_entity }
end
end
end
def destroy
@member.destroy
respond_to do |format|
format.html { redirect_to team_members_url }
format.json { head :no_content }
end
end
# Allow empty checkboxes
# http://railscasts.com/episodes/17-habtm-checkboxes
def initialize_check_boxes
params[:member][:role_ids] ||= []
end
end
_フォーム部分
<%= form_for [@team, @member], :html => { :class => 'form-horizontal' } do |f| %>
#...
# testing the count...
<ul>
<li>Captain - <%= Team.find(@member.team_id).members.captain.size %></li>
<li>Runner - <%= Team.find(@member.team_id).members.runner.size %></li>
<li>Driver - <%= Team.find(@member.team_id).members.driver.size %></li>
</ul>
<div class="control-group">
<div class="controls">
<%= f.fields_for :roles do %>
<%= hidden_field_tag "member[role_ids][]", nil %>
<% Role.all.each do |role| %>
<%= check_box_tag "member[role_ids][]", role.id, @member.role_ids.include?(role.id), id: dom_id(role) %>
<%= label_tag dom_id(role), role.title %>
<% end %>
<% end %>
</div>
</div>
#...
<% end %>