ruby on rails带有多态parent_id的Rails Factory Bot问题

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

我在FactoryBot上无法从具有多态关联抛出'parent'的Image模型创建Image的问题,并且当我想通过FactoryBot从Image创建实例但在CLI中出现此错误时:(ActiveModel :: MissingAttributeError:无法写入未知属性parent_id

我使用RSpec进行测试,并且我想测试图像模型

user.rb(图像的用户模型has_one头像)

class User < ApplicationRecord
  include Generals::SoftDelete

  include Methods::User
  include Scopes::User
  include Validations::User

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
  :recoverable, :rememberable, :validatable

  has_many :created_coffee_shop, class_name: 'CoffeeShop', foreign_key: 'creator_id'
  has_many :maintained_coffee_shop, class_name: 'CoffeeShop', foreign_key: 'maintainer_id'
  has_many :owened_coffee_shop, class_name: 'CoffeeShop', foreign_key: 'owner_id', dependent: :destroy
  has_many :enrolments
  has_many :enroled_tables, through: :enrolments, source: :table
  has_one :avatar, as: :parent, class_name: 'Image', dependent: :destroy

  #JWT config
  before_create :add_jti
  def add_jti
  self.jti ||= SecureRandom.uuid
  end


  #role config
  enum role: [:sys_master, :sys_admin, :sys_expert, :coffee_owner,:player]
  after_initialize :set_default_role, :if => :new_record?

  def set_default_role
    self.role ||= :player
  end

#soft delete config for davise
  def active_for_authentication?  
    raise ErrorHandling::Errors::User::DeletedUser.new(deleted_at: deleted_at) if deleted_at?  
    return true
  end 
end

image.rb(提供多态关联作为父级)

class Image < ApplicationRecord
    include Methods::Image
    include Scopes::Image
    include Validations::Image

    belongs_to :parent, polymorphic: true

    mount_uploader :image, AvatarUploader
end

image_spec.rb(测试图像工厂)

require 'rails_helper'

RSpec.describe Image, type: :model do
  describe "#validations" do
    it "should have a valid factory" do
        user = create(:player)
        image = build(:picture, parent: user, image: nil)
        expect(image).to be_valid
    end
  end
end

images.rb(图像工厂)

FactoryBot.define do
    factory :picture, class: Image do
        image { Rack::Test::UploadedFile.new(Rails.root.join('spec/support/defultAvatar.jpg')) }
        parent {|a| a.association(:player)}
    end
end

users.rb(用户工厂)

require 'faker'

FactoryBot.define do
  # :sys_master, :sys_admin, :sys_expert, :coffee_owner,:player

    factory :player, class: ApiUser do
      sequence(:email) { |n| "test#{n}#{rand(100000..999999).to_s}@player.com" }
      password { "123456" }
      role {"player"}
      jti {Faker::Alphanumeric.alphanumeric(number: 20)}
    end

    factory :coffee_owner, class: ApiUser do
      sequence(:email) { |n| "test#{n}#{rand(100000..999999).to_s}@coffee_owner.com" }
      password { "123456" }
      role {"coffee_owner"}
      jti {Faker::Alphanumeric.alphanumeric(number: 20)}
    end

    factory :sys_expert, class: ApiUser do
      sequence(:email) { |n| "test#{n}#{rand(100000..999999).to_s}@sys_expert.com" }
      password { "123456" }
      role {"sys_expert"}
      jti {Faker::Alphanumeric.alphanumeric(number: 20)}
    end

    factory :sys_admin, class: ApiUser do
      sequence(:email) { |n| "test#{n}#{rand(100000..999999).to_s}@sys_admin.com" }
      password { "123456" }
      role {"sys_admin"}
      jti {Faker::Alphanumeric.alphanumeric(number: 20)}
    end

    factory :sys_master, class: ApiUser do
      sequence(:email) { |n| "test#{n}#{rand(100000..999999).to_s}@sys_master.com" }
      password { "123456" }
      role {"sys_master"}
      jti {Faker::Alphanumeric.alphanumeric(number: 20)}
    end
end

schema.rb

ActiveRecord::Schema.define(version: 2019_12_09_070629) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "board_games", force: :cascade do |t|
    t.string "name", null: false
    t.string "publisher", null: false
    t.integer "min_player", null: false
    t.integer "max_player", null: false
    t.integer "play_time", null: false
    t.text "description"
    t.datetime "deleted_at"
    t.bigint "coffee_shop_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["coffee_shop_id"], name: "index_board_games_on_coffee_shop_id"
    t.index ["name", "coffee_shop_id"], name: "index_board_games_on_name_and_coffee_shop_id", unique: true
  end

  create_table "coffee_shops", force: :cascade do |t|
    t.string "name", null: false
    t.string "address", null: false
    t.bigint "owner_id", null: false
    t.bigint "creator_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.datetime "deleted_at"
    t.bigint "maintainer_id", null: false
    t.index ["creator_id"], name: "index_coffee_shops_on_creator_id"
    t.index ["maintainer_id"], name: "index_coffee_shops_on_maintainer_id"
    t.index ["owner_id"], name: "index_coffee_shops_on_owner_id"
  end

  create_table "enrolments", force: :cascade do |t|
    t.bigint "user_id"
    t.bigint "table_id"
    t.datetime "deleted_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["table_id"], name: "index_enrolments_on_table_id"
    t.index ["user_id", "table_id", "deleted_at"], name: "index_enrolments_on_user_id_and_table_id_and_deleted_at", unique: true
    t.index ["user_id"], name: "index_enrolments_on_user_id"
  end

  create_table "events", force: :cascade do |t|
    t.string "name", null: false
    t.string "description", null: false
    t.datetime "deleted_at"
    t.bigint "coffee_shop_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.datetime "opens_at", null: false
    t.datetime "enrol_start_time", null: false
    t.datetime "enrol_end_time", null: false
    t.datetime "event_start_time", null: false
    t.datetime "event_end_time", null: false
    t.datetime "closed_at", null: false
    t.index ["coffee_shop_id"], name: "index_events_on_coffee_shop_id"
  end

  create_table "images", force: :cascade do |t|
    t.string "image"
    t.string "parent_type"
    t.bigint "parent_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["parent_type", "parent_id"], name: "index_images_on_parent_type_and_parent_id"
  end

  create_table "tables", force: :cascade do |t|
    t.string "table_code", null: false
    t.datetime "deleted_at"
    t.bigint "event_id"
    t.bigint "board_game_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "capacity"
    t.integer "enroled", default: 0
    t.index ["board_game_id"], name: "index_tables_on_board_game_id"
    t.index ["event_id"], name: "index_tables_on_event_id"
    t.index ["table_code", "event_id"], name: "index_tables_on_table_code_and_event_id", unique: true
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "jti", null: false
    t.integer "role"
    t.datetime "deleted_at"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["jti"], name: "index_users_on_jti", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

  add_foreign_key "board_games", "coffee_shops"
  add_foreign_key "coffee_shops", "users", column: "creator_id"
  add_foreign_key "coffee_shops", "users", column: "maintainer_id"
  add_foreign_key "coffee_shops", "users", column: "owner_id"
  add_foreign_key "enrolments", "tables"
  add_foreign_key "enrolments", "users"
  add_foreign_key "events", "coffee_shops"
  add_foreign_key "tables", "board_games"
  add_foreign_key "tables", "events"
end

ruby-on-rails factory-bot rspec-rails polymorphic-relationship
1个回答
0
投票
我将在您的图像工厂尝试以下操作:association :parent, factory: :player

FactoryBot.define do factory :picture, class: Image do image { Rack::Test::UploadedFile.new(Rails.root.join('spec/support/defultAvatar.jpg')) } association :parent, factory: :player end end

© www.soinside.com 2019 - 2024. All rights reserved.