2014-01-21 3 views
0

Я новичок в FactoryGirl, в Ruby, я пытаюсь написать некоторый rspec, но у меня возникли проблемы с круговой зависимостью. Я искал и пробовал несколько вещей, последний породил бесконечный цикл, и мне пришлось отключить мой WM. (Proc 100%)FactoryGirl круговая зависимость и валидация

модели/ГОЛОСУЕМ

class Vote < ActiveRecord::Base 
    has_many :vote_options 

модели/vote_option

class VoteOption < ActiveRecord::Base 
    belongs_to :vote 
    accepts_nested_attributes_for :vote_options, reject_if: :all_blank 

спецификации/модели/vote_spec

describe Vote do 
    describe 'should return the good label' do 
    let(:nobody) { FactoryGirl.create(:vote, visibility: 0) } 
    it "should not be visible" do 
     nobody.intercom_custom_data[:visibility].should == I18n.t("votes.new.visibility_none") 
    end 
    end 
end 

SPEC/фабрики

factory :vote do 
    team 
    question 'Question?' 
    question_type 0 

    # Avoid validation because of the circular dependency. 
    # https://stackoverflow.com/questions/9322353/factory-girl-create-that-bypasses-my-model-validation 
    after(:build) do |vote| 
     vote.vote_options << VoteOption.create(vote_id: vote.id) 
     #vote.save!(:validate => false) 
    end 
    end 

    factory :vote_allowed do 
    user 
    vote 
    allowed 1 
    end 

    factory :vote_casted do 
    vote_allowed 
    vote_options 
    end 

    factory :vote_options do 
    vote 
    title 'default option' 
    end 

Это код, который сделал бесконечный цикл. Я предполагаю, что он создал голосование и голосование бесконечно из-за круговой зависимости.

Итак, у меня есть голосование, у которого есть много голосовых_потоков (выбор пользователя), каждый vote_options содержит свой родительский идентификатор. Валидация отвергает создание, если поля пустые, у нас нет проблем с этим кодом, чтобы сохранить новое голосование/vote_options, потому что все сделано в одной транзакции.

Но, с rspec, я не могу создать одновременно голосование и vote_options строк в зависимости друг от друга. (Или я не знаю, как это сделать)

Таким образом, я пытался избежать проверки, как это:

after(:create) do |vote| 
    VoteOption.create(vote_id: vote.id) 
    vote.save!(:validate => false) 
end 

Но я получил ошибку:

Failure/Error: let(:nobody) { FactoryGirl.create(:vote, visibility: 0) } 
ActiveRecord::RecordInvalid: 
    Validation failed: Vote options can't be blank 

Я пытался используйте after_create вместо after(:create), но мой FactoryGirl в 4.3, поэтому after_create больше не существует. Я нашел учебник о том, как использовать after_create в> 3.3 "в https://stackoverflow.com/questions/15003968/undefined-method-after-create-with-factorygirl, но он не работает для меня, я не должен получать« параметры голосования не могут быть пустыми »... Поэтому я взглянул на документ, связанный в предыдущей ссылке, и я попытался добавить в спецификации/фабрики

FactoryGirl.define do 
    after(:create) {|instance| instance.create } 

Но я не очень понимаю, что я должен делать, и я не понимаю, где проблема. Есть идеи?

Edit # 1:

factory :vote do 
    team 
    question 'Question?' 
    question_type 0 

    association :vote_options, factory: :vote_options 
    # tried with :create and :build 
    after(:create) do |vote, evaluator| 
     create_list(:vote_options, 1, vote: vote) 
    end 
    end 
+0

Как выглядит ваш вопрос, который вызывает эту проблему? –

+0

Я не уверен, чтобы четко понять вопрос. У меня нет проблем в других спецификациях. Проблема здесь связана с тем, как модели разрабатываются с циклической зависимостью, и потому что валидация отказывается создавать новые экземпляры, если поля пустые, поэтому мне нужно избегать проверки. Я сделал это с помощью 'vote.save! (: Validate => false)' и, похоже, работал, потому что я не получил пустые поля ", но вместо этого я получил значение" after_create is not function ", поэтому я использовал" after (: create) », но я снова получил« пустые поля », поэтому я не знаю, что здесь не работает. – Vadorequest

+0

Почему вы не используете * factorygirl * association? –

ответ

1

Вы пытались сделать в соответствии с ассоциации главу document?

ignore do 
    vote_options_count = 1 
end 

after(:build) do | vote, evaluator | 
    create_list(:vote_option, evaluator.vote_options_count, vote: vote) 
end 

После того, что он должен быть разрешен доступ к следующим образом:

create(:vote).vote_options.length # 0 
create(:vote, vote_options_count: 15).vote_options.length # 15 

ПРИМЕЧАНИЕ: vote_option завод должен быть определен как из одного, а не множественное число.

+0

Но я не могу определить vote_options раньше, ему также нужно проголосовать за определение ... ^^ ' – Vadorequest

+0

@Vadorequest, почему вы не можете использовать shell для определения 'vote_option' - единого, а не множественного числа? –

+0

Возможно, вы правы, поэтому на фабриках.rb я изменил vote_options на vote_option, но я получил: Failure/Error: Не удалось найти соответствующую строку из backtrace SystemStackError: Уровень слишком глубокий уровень – Vadorequest

0

Я сделал, как тат:

спецификации/фабрики

factory :vote_option do 
    vote 
    title 'default option' 
    end 

    factory :vote do 
    team 
    question 'Question?' 
    question_type 0 
    vote_options_attributes {[{ 
     title: 'foo' 
    }]} 
    end 

    factory :vote_allowed do 
    user 
    vote 
    allowed 1 
    end 

    factory :vote_casted do 
    vote_allowed 
    vote_option 
    end 

спецификации/модели/vote_spec

describe Vote do 

    describe 'should return the good label' do 
    let(:nobody) { FactoryGirl.create(:vote, visibility: 0) } 

    it "should not be visible" do 
     #nobody.intercom_custom_data[:visibility].should == I18n.t("votes.new.visibility_none") 
     puts nobody.inspect 
     puts nobody.vote_options.inspect 
    end 

    end 
end 

Консольные:

Run options: exclude {:semaphore_ignore=>true} 
#<Vote id: 1, users_id: nil, teams_id: 1, datetime: "2014-01-21 13:42:37", question: "Question?", question_type: 0, not_vote: 0, hidden: nil, visibility: 0> 
[#<VoteOption id: 1, vote_id: 1, title: "foo", votes: 0, created_at: "2014-01-21 12:42:37", updated_at: "2014-01-21 12:42:37">] 

Я не использую никаких ассоциаций, ни одного списка, я просто вынужден добавить options_attributes для создания автоматически vote_options, когда голосование создано. (Как мы делаем, когда мы создаем новое голосование из браузера)

Спасибо, majioa.

Смежные вопросы