Метод has_and_belongs_to_many для объединения моделей не рекомендуется в пользу нового подхода has_many ...: through. Управлять данными, хранящимися в отношении has_and_belongs_to_many, очень сложно, так как Rails не предоставляет методов по умолчанию, но метод: through является первоклассной моделью и может использоваться как таковой.
Что касается вашей проблемы, вы можете решить ее следующим образом:
class Competition < ActiveRecord::Base
has_many :participating_teams
has_many :teams,
:through => :participating_teams,
:source => :team
end
class Team < ActiveRecord::Base
has_many :participating_teams
has_many :competitions,
:through => :participating_teams,
:source => :competition
end
class ParticipatingTeam < ActiveRecord::Base
belongs_to :competition
belongs_to :team
end
Когда речь идет о создании самих команд, вы должны структурировать свою форму так, чтобы один из полученных вами параметров был отправлен в виде массива. Как правило, это делается путем указания того, что все поля флажков имеют одинаковое имя, например «соревнования []», а затем для каждого флажка устанавливается значение, равное идентификатору соревнования. Тогда контроллер будет выглядеть примерно так:
class TeamsController < ApplicationController
before_filter :build_team, :only => [ :new, :create ]
def new
@competitions = Competitions.all
end
def create
@team.save!
# .. usual if logic on save
rescue ActiveRecord::RecordInvalid
new
render(:action => 'new')
end
protected
def build_team
# Set default empty hash if this is a new call, or a create call
# with missing params.
params[:team] ||= { }
# NOTE: HashWithIndifferentAccess requires keys to be deleted by String
# name not Symbol.
competition_ids = params[:team].delete('competitions')
@team = Team.new(params[:team])
@team.competitions = Competition.find_all_by_id(competition_ids)
end
end
Установка статуса отмеченного или не отмеченного для каждого элемента в вашем списке флажков выполняется чем-то вроде:
checked = @team.competitions.include?(competition)
Где «соревнование» - это то, что повторяется.
Вы можете легко добавлять и удалять элементы из вашего списка соревнований, или просто переназначить весь список, и Rails определит новые отношения на его основе. Ваш метод обновления не будет отличаться от нового метода, за исключением того, что вы будете использовать update_attributes вместо new.