Машинист, как мне сослаться на созданный объект и передать его ассоциации? (AssociationTypeMismatch)

Я пытаюсь построить фабрики по относительно сложным моделям.

У меня есть модель Pressroom, которая принадлежит Source, а у Source есть много Pressroom. При создании источника, если печатные помещения пусты, начальное печатное помещение создается в фильтре after_create. Сайт прессы должен быть уникальным для каждого источника.

class Source
  has_many :pressrooms
  after_create :create_initial_pressroom! # if pressrooms.empty?
  ...
end

class Pressroom
  belongs_to :source
  # source.pressrooms.map(&:site) should have unique elements
  validate_on_create :check_unique_site
end

Это приводит к моей проблеме: My Pressroom.make терпит неудачу, потому что он создает источник, в котором нет пресс-цехов, поэтому обратный вызов after_create создает его, и когда Pressroom.make пытается завершить работу, его сайт не уникален. Я не хочу создавать два печатных цеха при запуске Pressroom.make

Моя попытка решить эту проблему состоит в том, чтобы сделать ссылку на источник в чертеже пресс-центра ссылкой на пресс-центр. Вроде того, что сделал бы Source.create :pressrooms => [Pressroom.new].

Pressroom.blueprint do
  source { Source.make :pressrooms => [self] }
  site { source.site }
end

К сожалению, self еще не является пресс-центром. Это экземпляр Machinist :: Lathe, поэтому я получаю исключение ActiveRecord :: AssociationTypeMismatch.

Я немного новичок, когда дело касается фабрик и машиниста. Я не хочу менять бизнес-логику, и я хочу иметь возможность чистить печатные цеха с Pressroom.make, не создавая при этом два печатных цеха. Если переключение на фабричную девушку поможет, я открыт для этого.

Буду благодарен за любые идеи, как это решить.


person Martin Svalin    schedule 24.03.2011    source источник


Ответы (2)


Погуглив, я нашел несколько подсказок по http://webcrisps.wordpress.com/2009/08/13/stubbing-before_create-callbacks-in-a-machinist-blueprint/ - чтобы заглушить обратный вызов after_create :create_initial_pressroom! в исходном коде в схеме исходного кода - с помощью Machinist 2 и Мокко здесь:

Pressroom.blueprint do
  source { Source.make!(:without_initial_pressroom) }
  site   { object.source.site }
end

Source.blueprint do
  site
end

Source.blueprint(:without_initial_pressroom) do
  object.stubs(:create_initial_pressroom!).returns(true)
end

Таким образом, Pressroom.make! работает так, как должно, Source.make! работает так, как должно, и ... Думаю, я счастлив. Но все еще немного озадачен проблемами, с которыми я столкнулся в решении, которое я пробовал выше (как у машиниста 1, так и у машиниста 2).

Если кто-нибудь знает, как заставить это работать с object, дайте мне знать. Это было бы намного чище, и, кроме того, я обычно не люблю принимать свои собственные ответы здесь, в stackoverflow.

person Martin Svalin    schedule 24.03.2011

Вы используете Машинист 1 или 2? Эти предложения для Machinist 2 и могут работать, а могут и не работать в Machinist 1. Я не могу вспомнить, как вы это делаете в Machinist 1 (и меня не беспокоит гуглить!).

Чтобы сделать это так, как вы предлагаете, вам нужно использовать object:

Pressroom.blueprint do
  source { Source.make :pressrooms => [object] }
  site { source.site }
end

Но гораздо лучший способ сделать это - воспользоваться тем фактом, что Machinst знает об ассоциациях моделей, и просто позволить ему делать свое дело:

Pressroom.blueprint do
  source
  site { source.site }
end

Если ваши ассоциации настроены правильно, это должно работать. Дополнительную информацию см. На вики-странице Blueprints.

person idlefingers    schedule 24.03.2011
comment
Я использую машинист 1, но попробую версию 2. object не работал в версии 1, он установил мой источник на nil. Проблема с простым планом состоит в том, что Pressroom.make выполнит Source.make, который запускает обратный вызов after_create, создает пресс-центр, возвращается в Pressroom.make, что не удается из-за уникального ограничения. - person Martin Svalin; 24.03.2011
comment
Я также пробовал с машинистом 2, но, похоже, это не сработало. Pressroom.make! выбрасывает undefined method site 'на ноль: NilClass. Source isn't set. I've tried different approaches in the blueprint: source, source {Source.make! : pressrooms = ›[object]} , site {source.site} , site {object.source.site}` ... все, что я получаю, это undefined method 'site': / - person Martin Svalin; 24.03.2011
comment
хммм, я думаю, что object.source.site верен для машиниста 2, но когда он вызывается, возможно, исходный код еще не создан. Вы пробовали комбинацию make! в источнике с object.source.size для сайта? - person idlefingers; 24.03.2011
comment
да, попробовал ... теперь ищу альтернативное решение на основе webcrisps.wordpress.com/2009/08/13/ - заглушка обратного вызова after_create. Не совсем то, что я хотел, так как я бы предпочел Source.make! вести себя нормально. - person Martin Svalin; 24.03.2011