Подтвердить что ты не робот

FactoryGirl: attributes_for не дает мне связанных атрибутов

У меня есть модель кода factory следующим образом:

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

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

  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 не возвращает все необходимые атрибуты, как это делает create.

[email protected]:~/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"}

Любые идеи?

Спасибо,

4b9b3361

Ответ 2

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

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

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

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

Ответ 3

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

attr = attributes_for(:code).merge(code_type: create(:code_type))

Ответ 4

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

conf = FactoryGirl.build(:conference)
post :create, {:conference => conf.attributes.slice(*conf.class.accessible_attributes) }

Ответ 5

Я синтезировал то, что говорили другие, в случае, если это помогает кому-то еще. Чтобы соответствовать версии 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

Ответ 6

В моем APP/spec/controller/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

Ответ 7

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

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

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

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