Сохраняя активную запись, в каком порядке сохраняются связанные объекты? - PullRequest
8 голосов
/ 20 апреля 2010

В рельсах при сохранении объекта active_record также будут сохранены связанные с ним объекты. Но ассоциации has_one и has_many имеют разные порядки сохранения объектов.

У меня есть три упрощенные модели:

class Team < ActiveRecord::Base
  has_many :players
  has_one :coach
end

class Player < ActiveRecord::Base
  belongs_to :team
  validates_presence_of :team_id
end

class Coach < ActiveRecord::Base
  belongs_to :team
  validates_presence_of :team_id
end

Я ожидал, что при вызове team.save команда должна быть сохранена перед ассоциированным тренером и игроками.

Я использую следующий код для тестирования этих моделей:

t = Team.new
team.coach = Coach.new
team.save!

team.save! возвращает true.

Но в другом тесте:

t = Team.new
team.players << Player.new
team.save!

team.save! выдает следующую ошибку:

> ActiveRecord::RecordInvalid:
> Validation failed: Players is invalid

Я выяснил, что team.save! сохраняет объекты в следующем порядке: 1) игроки, 2) команда и 3) тренер. Вот почему я получил ошибку: когда игрок спасен, команда еще не имеет идентификатора, поэтому validates_presence_of :team_id терпит неудачу в игроке.

Может кто-нибудь объяснить мне, почему объекты сохраняются в этом порядке? Мне кажется, это не логично.

Ответы [ 2 ]

0 голосов
/ 08 марта 2013

Давайте посмотрим на ваш провальный тест:

t = Team.new
team.players << Player.new
team.save!

Добавление нового игрока в ассоциацию team.players пытается установить team_id для игроков прямо в строке 2. Вот как работает оператор <<. Он не обновляется, когда вы сохраняете команду, поэтому, даже если команда будет сохранена первой, у игрока все равно будет нулевой team_id. В этом случае вы можете легко решить эту проблему, поменяв местами строки 2 и 3. </p>

0 голосов
/ 20 апреля 2010

Вы должны использовать «validates_associated» для достижения этого

отметка Здесь

Что-то вроде следования без проверки, хотя

class Team < ActiveRecord::Base
  has_many :players
  has_one :coach
  validates_associated :players, :coach  ###MOST IMPORTANT LINE 
end

class Player < ActiveRecord::Base
  belongs_to :team
  validates_presence_of :team_id
end

class Coach < ActiveRecord::Base
  belongs_to :team
  validates_presence_of :team_id
end

В вашем контроллере

t = Team.new

@coach = t.build_coach(:column1=> "value1", :column2=> "value2" )  # This create new object with @coach.team_id= t.id
@players = t.players.build

t.save#This will be true it passes the validation for all i.e. Team, COach & Player also save all at once otherwise none of them will get saved.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...