I'm building a toy Rails app that will run tournaments. The thing with this type of tournament is though is that rounds can have both multiple input rounds and multiple output rounds (i.e., you can't model a tournament's rounds as a tree, but it's still a DAG).
I'm running into an issue where I believe I have my associations set up properly, but Rails is complaining about the models suddenly becoming invalid, and I can't figure out how to get more information.
I have these relevant ActiveModel classes:
class Round < ApplicationRecord
belongs_to :tournament
has_and_belongs_to_many :players
has_many :previous_round_edges, foreign_key: :end_id, class_name: "RoundEdge"
has_many :previous_rounds, through: :previous_round_edges, source: :start
has_many :next_round_edges, foreign_key: :start_id, class_name: "RoundEdge"
has_many :next_rounds, through: :next_round_edges, source: :end
end
class RoundEdge < ApplicationRecord
belongs_to :start, foreign_key: :start_id, class_name: "Round"
belongs_to :end, foreign_key: :end_id, class_name: "Round"
end
The code in question that triggers errors:
final_round = rounds.build()
players.each_slice(4) do |player_chunk|
round = rounds.build(players: player_chunk, position: round_position)
# Objects are valid right until we start associating them with each other
round.next_rounds << final_round
final_round.previous_rounds << round
end
I've also tried throwing in a debugger, and these are the results:
round.errors
=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=next_round_edges, type=invalid, options={}>, #<ActiveModel::Error attribute=next_rounds, type=invalid, options={}>]>
final_round.errors
=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=previous_round_edges, type=invalid, options={}>, #<ActiveModel::Error attribute=previous_rounds, type=invalid, options={}>]>
If I look at the relations though, they seem correct:
round
=> #<Round:0x000000010fc0e760 id: nil, position: 0, next_round_id: nil, tournament_id: nil, created_at: nil, updated_at: nil>
final_round
=> #<Round:0x00000001104e2580 id: nil, position: nil, next_round_id: nil, tournament_id: nil, created_at: nil, updated_at: nil>
round.previous_rounds
=> []
round.next_rounds
=> [#<Round:0x00000001104e2580 id: nil, position: nil, next_round_id: nil, tournament_id: nil, created_at: nil, updated_at: nil>]
final_round.previous_rounds
=> [#<Round:0x000000010fc0e760 id: nil, position: 0, next_round_id: nil, tournament_id: nil, created_at: nil, updated_at: nil>]
final_round.next_rounds
=> []
So it looks like they point to each other fine, but I can't figure out what is going on.
Thanks!