2012-05-02 2 views
18

В приложении Rails, учитывая три модели пользователя, статьи и рецензент со следующими отношениями и валидациями:Как пользователь завод девушка создавать связанные списки с has_many с проверкой, которая требует его на создание

class User < ActiveRecord::Base 
    has_many :articles 
    has_many :reviewers 
end 

class Reviewer < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :article 
end 

class Article < ActiveRecord::Base 
    belongs_to :user 
    has_many :reviewers 

    validate :has_reviewers? 

    def has_reviewers? 
    errors.add(:base, "article must have at least one reviewer.") if self.reviewers.blank? 
    end 
end 

И следующие заводы, использующие новый DSL:

FactoryGirl.define do 

    factory :user do 
    name { (8...20).map{ ('a'..'z').to_a[rand(26)] }.join } 
    age { Kernel.rand(100) } 
    end 

    factory :article do 
    body "This is the article content" 
    title "This is the title" 
    user 
    after_create do |article| 
     article.reviewers = create_list(:user, 2) 
    end 
    end 

    factory :reviewer do 
    user 
    article 
    state { ["published","draft","rejected","archived"][Kernel.rand(4)] } 
    end 

end 

завод, чтобы создать статью, не работает, потому что проверка не пройдена до создания рецензентов:

> FactoryGirl.create(:article) 
ActiveRecord::RecordInvalid: Validation failed: article must have at least one reviewer. 

Я сделал больше попыток, чем хотел бы признать попытку преодолеть это препятствие, но я застрял! Одна из идей, у меня были создать рецензент так:

factory :article do 
    body "This is the article content" 
    title "This is the title" 
    user 
    reviewers {|a| [FactoryGirl.create(:reviewer, article: a)] } 
    end 

, но в этом контексте, «а» не экземпляр. Так что это тоже не работает, как раньше.

ответ

3
factory :article do 
    reviewers {|a| [a.association(:reviewer)] } 
end 

или

factory :article do 
    before_create do |a| 
    FactoryGirl.create(:reviewer, article: a) 
    end 
end 
+0

Когда я пытаюсь это, я получаю: SystemStackError: уровень стека слишком глубоко. Похоже, что когда фабрика рецензентов уволили, она не знает об этой статье, поэтому пытается создать еще одну статью. – Blizzo

+0

@Blizzo Вы можете удалить создание статьи с фабрики рецензента или использовать before_create. Я отредактировал свой ответ, чтобы отразить это. – Unixmonkey

+0

Я также добавил ваш второй пример, после того как вы добавили его и получили ошибку проверки: ActiveRecord :: RecordInvalid: не удалось выполнить проверку: у статьи должен быть хотя бы один рецензент. – Blizzo

22

Я повторно отправил это более на странице GitHub Factory Girl, как вопрос и работал мой путь вокруг к ответу:

before_create do |article| 
    article.reviewers << FactoryGirl.build(:reviewer, article: article) 
end 

Ключ делает это в a before_create, поэтому проверки еще не запущены и убедитесь, что он снова запустил вновь созданного рецензента в список отзывов о создаваемом экземпляре. Благодаря Unixmonkey реагирования и держит меня пробовать новые вещи :)

https://github.com/thoughtbot/factory_girl/issues/369#issuecomment-5490908

+0

У меня была аналогичная проблема, и это решило проблему. Благодаря! – ryanpitts1

1

Новый синтаксис:

before(:create) do |article| 
    article.reviewers << FactoryGirl.build(:reviewer, article: article) 
end