背景:
我正在尝试创建一个与has_one/belongs_to相关的FactoryBot对象。
User has_one Car
Car has_one Style
Style has an attribute {style_number:"1234"}
问题
我的控制器引用了用户,用户拥有一个汽车,汽车又拥有一个样式,我需要在FactoryBot中设置这些值。
我该如何创建一个用户,同时拥有一个具有样式对象的汽车对象?
我已经阅读了文档https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md
然而,我不理解他们建议如何做。我已经弄清楚了需要嵌套三个对象,但是对语法感到困惑。
控制器
before_action :authenticate_user!
before_action :set_steps
before_action :setup_wizard
include Wicked::Wizard
def show
@user = current_user
@form_object = form_object_model_for_step(step).new(@user)
render_wizard
end
private
def set_steps
if style_is_1234
self.steps = car_steps.insert(1, :style_car)
else
self.steps = car_steps
end
end
def style_is_1234
if params.dig(:form_object, :style_number)
(params.dig(:form_object, :style_number) & ["1234"]).present?
else
(current_user.try(:car).try(:style).try(:style_number) & ["1234"]).present?
end
end
def car_steps
[:type,:wheel, :brand]
end
Rspec测试
用户工厂
FactoryBot.define do
factory :user, class: User do
first_name { "John" }
last_name { "Doe" }
email { Faker::Internet.email }
password { "somepassword" }
password_confirmation { "some password"}
end
end
测试方法前置处理
before(:each) do
@request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryBot.create(:user)
sign_in user
测试
context "Requesting with second step CarStyle" do
it "should return success" do
get :show, params: { :id => 'car_style' }
expect(response.status).to eq 200
end
end
目前该测试失败,因为User.Car.Style.style_number未设置为“1234”。
试验1 (https://github.com/thoughtbot/factory_bot_rails/issues/232)
FactoryBot.define do
factory :user, class: User do
first_name { "John" }
last_name { "Doe" }
email { Faker::Internet.email }
password { "somepassword" }
password_confirmation { "some password"}
car
end
end
FactoryBot.define do
factory :car, class: Car do
make { "Holden" }
model { "UTE" }
end
end
FactoryBot.define do
factory :style, class: Style do
color { "blue" }
for_car
trait :for_car do
association(:styable, factory: :car)
end
end
end
来自Trail 1的错误
SystemStackError: 栈级别太深
Trail 2
我尝试了srng的建议
编辑:对于多态关联,请尝试;
FactoryBot.define do
factory :car, class: Car do
make { "Holden" }
model { "UTE" }
association :stylable, factory: :style
end
end
并且出现了错误:
ActiveRecord::RecordInvalid:验证失败:Stylable必须存在
我认为这是一个Rails 5问题。https://github.com/rails/rails/issues/24518
但是,我想保留我的代码,并添加optional:true。有什么方法可以做到这一点吗?
Trail 3
FactoryBot.define do
factory :car, class: Car do
make { "Holden" }
model { "UTE" }
after(:create) do |car|
create(:style, stylable: car)
end
end
end
我尝试了Srng的第二个建议,虽然它对他有效,但我得到了一个略微不同的错误:
ActiveRecord :: RecordInvalid: 验证失败:用户必须存在