rails has_many через создание нескольких записей соединения с collection_select

Я довольно новичок в rails и пытаюсь заставить три модели работать вместе с помощью отношения has_many посредством альтернативных имен классов в модели соединения и формы collection_select для добавления записей в модель соединения. Три модели ниже. У меня есть "accepts_nested_attributes_for" для всех ассоциаций.

Модель пользователя

has_many :match_opponents
has_many :home_opponents, :class_name => 'MatchOpponent', :foreign_key => 'home_opponent_id'
has_many :away_opponents, :class_name => 'MatchOpponent', :foreign_key => 'away_opponent_id'
has_many :matches, :through => :match_opponents

Модель соответствия

has_many :match_opponents
has_many :home_opponents, :class_name => 'MatchOpponent', :foreign_key => 'home_opponent_id'
has_many :away_opponents, :class_name => 'MatchOpponent', :foreign_key => 'away_opponent_id'
has_many :users, :through => :match_opponents

Модель противника

belongs_to :user, :inverse_of => :match_opponents
belongs_to :match, :inverse_of => :match_opponents

Контроллер My Matches для нового и создания:

def new
  @match = Match.new
  @match.home_opponents.build
  @match.away_opponents.build
end

def create
  @match = Match.create(match_params)
  @home_opponents = @match.home_opponents.create!(params[:match_opponents])
  @away_opponents = @match.away_opponents.create!(params[:match_opponents])
  if @match.save 
    redirect_to @match, notice: 'Match was successfully created.'
  end
end

Моя форма:

= simple_form_for @match, html: { multipart: true } do |f|
  = simple_fields_for :home_opponents do |ff|
    = ff.collection_select :user_id, User.all, :id, :name, {}, {multiple: true}

  = simple_fields_for :away_opponents do |ff|
    = ff.collection_select :user_id, User.all, :id, :name, {}, {multiple: true}

Соответствующие допустимые параметры для каждой модели:

def match_params
  params.require(:match).permit(Match::MATCH_ATTRIBUTES)
end

MATCH_ATTRIBUTES = [:match_opponent_ids => [], :user_ids => [], match_opponents_attributes: MatchOpponent::MATCH_OPPONENT_ATTRIBUTES]

def user_params
  params.require(:user).permit(User::USER_ATTRIBUTES)
end

USER_ATTRIBUTES = [:match_opponent_ids => [], :match_ids => [], :match_opponents_attributes: MatchOpponent::MATCH_OPPONENT_ATTRIBUTES]

def match_opponent_params
  params.require(:match_opponent).permit(MatchOpponent::MATCH_OPPONENT_ATTRIBUTES)
end

MATCH_OPPONENT_ATTRIBUTES = [:id, :home_opponent_id, :away_opponent_id, :match_id, :user_id]

Я перепробовал множество различных конфигураций моделей, но не могу получить несколько записей в модели соединения (MatchOpponent) для сохранения с записанными как match_id, так и user_id.

Заранее благодарю за любую помощь!

2 ответа

Решение

Для начала вам нужно больше узнать о действиях контроллера. Вы можете прочитать о них в Руководствах по Rails.

Например:

def create
  @match = Match.create(match_params)
  @home_opponents = @match.home_opponents.create!(params[:match_opponents])
  @away_opponents = @match.away_opponents.create!(params[:match_opponents])
  if @match.save 
    redirect_to @match, notice: 'Match was successfully created.'
  end
end

Match.create уже сохраняет объект, который вы сохраняете снова if @match.save, Это должно выглядеть так:

def create
  @match = Match.new(match_params)
  if @match.save 
    #create opponents here
    redirect_to @match, notice: 'Match was successfully created.'
  end
end

Спасибо! Решил это следующим. Необходимо создать альтернативные классы в модели User, а не в модели соединения (MatchOpponent):

Модель пользователя

has_many :match_opponents
has_many :matches, :through => :match_opponents
has_many :home_opponents, :through => :match_opponents
has_many :away_opponents, :through => :match_opponents

Модель соответствия

has_many :match_opponents
has_many :home_opponents, :through => :match_opponents
has_many :away_opponents, :through => :match_opponents

Модель противника

belongs_to :home_opponent, :class_name => 'User', :foreign_key => 'home_opponent_id'
belongs_to :away_opponent, :class_name => 'User', :foreign_key => 'away_opponent_id'
belongs_to :match, :inverse_of => :match_opponents

Все вышеперечисленное имеет accept_nested_attributes_for.

Контроллер My Matches для нового и создания:

def new
  @match = Match.new
end

def create
  @match = Match.new(match_params)
  @match.update!(:status => 'pending')
  if @match.save 
    @match.match_opponents.where.not(:home_opponent_id => 'nil').each do |o| o.update!(:user_id => o.home_opponent_id) end
    @match.match_opponents.where.not(:away_opponent_id => 'nil').each do |o| o.update!(:user_id => o.away_opponent_id) end
   redirect_to @match, notice: 'Match was successfully created.'
  end
end

Моя форма:

= f.collection_select :home_opponent_ids, User.order(:first_name), :id, :name, {}, {multiple: true}
= f.collection_select :away_opponent_ids, User.order(:first_name), :id, :name, {}, {multiple: true}
Другие вопросы по тегам