使用has_one关系创建FactoryBot用户

问题描述 投票:1回答:1

Background:

我正在尝试创建一个与has_one / belongs_to相关的FactoryBot对象

用户has_one Car

Car has_one Style

Style有一个属性{style_number:“1234”}

Question

我的控制器引用用户,用户has_one Car,Car has_one Style,我需要在FactoryBot中设置这些值。

如何创建具有Car对象的User,该User具有Style对象?

我阅读了文档https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md

但是,我不明白他们如何推荐这样做,我想我需要嵌套三个对象,但对语法感到困惑。

Controller

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

私人的

   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 Test

Factory :User

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 method

 before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      user = FactoryBot.create(:user)
      sign_in user

测试

User needs to be signed in and User.car.style.style_number needs to be set to "1234"
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”。

Trial 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

来自路径1的错误

SystemStackError:堆栈级别太深

小径2

我试过srng的推荐

编辑:对于多态关联尝试;

FactoryBot.define做工厂:汽车,类:汽车做{“Holden”}模型{“UTE”}协会:stylable,工厂:: style end end

并得到错误:

ActiveRecord :: RecordInvalid:验证失败:样式必须存在

我认为这是一个轨道5问题。 https://github.com/rails/rails/issues/24518

但是,我想保留我的代码添加可选:true。有什么办法吗?

小道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:验证失败:用户必须存在

ruby-on-rails rspec factory-bot ruby-on-rails-5.2
1个回答
1
投票

为了创建依赖的工厂,您必须为每个模型创建一个工厂,然后只需将依赖的Model名称添加到您的工厂,即。

    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" }
        style
      end
    end


FactoryBot.define do
      factory :style, class: Style do
        color { "blue" }
      end
    end

编辑:相关代码;

# Factories
FactoryBot.define do
      factory :user, class: User do
        first_name { "John" }
        last_name  { "Doe" }
        email { Faker::Internet.email }
        password { "somepassword" }
        password_confirmation { "some password"}
        after(:create) do |user|
          user.car ||= create(:car, :user => user)
        end
      end
    end

  factory :style, class: Style do
    style_number { "Blue" }
  end

  factory :car, class: Car do
    name { "Holden" }
    trait :style do
      association :stylable, factory: :style
    end
end

#models
class Car < ApplicationRecord
  has_one :style, as: :styleable
end

class Style < ApplicationRecord
  belongs_to :styleable, polymorphic: true
  belongs_to :car
end

# Migrations - The belongs_to is the only important one
class CreateStyles < ActiveRecord::Migration[5.2]
  def change
    create_table :styles do |t|
      t.string :style_number
      t.belongs_to :stylable, polymorphic: true
      t.timestamps
    end
  end
end

class CreateCars < ActiveRecord::Migration[5.2]
  def change
    create_table :cars do |t|
      t.string :name
      t.timestamps
    end
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.