FactoryGirl: attribute_for не дает мне связанных атрибутов - PullRequest
30 голосов
/ 24 февраля 2011

У меня есть заводская модель кода, как это:

Factory.define :code do |f|
    f.value "code"
    f.association :code_type
    f.association(:codeable, :factory => :portfolio)
end

Но когда я тестирую свой контроллер с помощью простого кода test_should_create_cе, например:

  test "should create code" do
    assert_difference('Code.count') do
      post :create, :code => Factory.attributes_for(:code)
    end
    assert_redirected_to code_path(assigns(:code))
  end

... тест не пройден. Новая запись не создана.

В консоли кажется, что attributes_for не возвращает все обязательные атрибуты, как при создании.

rob@compy:~/dev/my_rails_app$ rails console test
Loading test environment (Rails 3.0.3)
irb(main):001:0> Factory.create(:code)
=> #<Code id: 1, code_type_id: 1, value: "code", codeable_id: 1, codeable_type: "Portfolio", created_at: "2011-02-24 10:42:20", updated_at: "2011-02-24 10:42:20">
irb(main):002:0> Factory.attributes_for(:code)
=> {:value=>"code"}

Есть идеи?

Спасибо

Ответы [ 7 ]

23 голосов
/ 24 февраля 2011

Вы можете попробовать что-то вроде этого:

(Factory.build :code).attributes.symbolize_keys 

Проверьте это: http://groups.google.com/group/factory_girl/browse_thread/thread/a95071d66d97987e)

10 голосов
/ 11 июля 2012

Это не возвращает отметки времени и т. Д., Только атрибуты, которые доступны для массового назначения:

(FactoryGirl.build :position).attributes.symbolize_keys.reject { |key, value| !Position.attr_accessible[:default].collect { |attribute| attribute.to_sym }.include?(key) }

Тем не менее, это довольно уродливо. Я думаю, что FactoryGirl должна предоставить что-то подобное из коробки.

Я открыл запрос на это здесь .

9 голосов
/ 11 сентября 2012

Я бы предложил еще один подход, который мне кажется более понятным:

attr = attributes_for(:code).merge(code_type: create(:code_type))
2 голосов
/ 20 марта 2013

Я синтезировал то, что сказали другие, на случай, если это кому-нибудь поможет.Чтобы соответствовать рассматриваемой версии FactoryGirl, я использовал Factory.build () вместо FactoryGirl.build ().Обновите при необходимости.

def build_attributes_for(*args)
  build_object = Factory.build(*args)
  build_object.attributes.slice(*build_object.class.accessible_attributes).symbolize_keys
end

Просто вызовите этот метод вместо Factory.attributes_for:

post :create, :code => build_attributes_for(:code)

Полный смысл (в пределах вспомогательного модуля) здесь: https://gist.github.com/jlberglund/5207078

2 голосов
/ 10 декабря 2012

вот что я в итоге делаю ...

conf = FactoryGirl.build(:conference)
post :create, {:conference => conf.attributes.slice(*conf.class.accessible_attributes) }
0 голосов
/ 03 июля 2017

Вот другой способ.Возможно, вы захотите пропустить атрибуты id, created_at и updated_at.

FactoryGirl.build(:car).attributes.except('id', 'created_at', 'updated_at').symbolize_keys

Ограничения:

  • Не генерирует атрибуты для ассоциаций HMT и HABTM (так как эти ассоциации хранятся в таблице соединений, а не в действительностиатрибут).
  • Стратегия ассоциации на фабрике должна быть create, как в association :user, strategy: :create.Эта стратегия может сделать вашу фабрику очень медленной, если вы не используете ее с умом.
0 голосов
/ 14 августа 2013

В моем приложении / spec / controllers / pages_controllers_spec.rb я установил:

let(:valid_attributes) { FactoryGirl.attributes_for(:page).merge(subject: FactoryGirl.create(:theme), user: FactoryGirl.create(:user)) } 

Потому что у меня есть две связанные модели. Это тоже работает:

 FactoryGirl.define do
    factory :page do
       title      { Faker::Lorem.characters 12 }
       body       { Faker::Lorem.characters 38 }
       discution  false
       published  true
       tags       "linux, education, elearning"
       section   { FactoryGirl.create(:section) }
       user      { FactoryGirl.create(:user)    }                                                                                                                            
     end
  end
...