【问题标题】:factorygirl with polymorphic associations and accepted nested attributes fails validations具有多态关联和接受的嵌套属性的 factorygirl 验证失败
【发布时间】:2016-08-05 00:54:57
【问题描述】:

我有一个非常简单的 poly 关联设置。我正在尝试验证令牌仅存在于提供商或商店中,而不是两者。当我使用 pry 时,这些验证可以正常工作,但是,我的重构使工厂陷入困境。

问题

如果您使用令牌创建商店,即 FactoryGirl.create(:shop, :with_authentication_token) 它会爆炸,因为无法像 FG 尝试处理它那样创建和保存商店?谁能指出我建立商店工厂的正确方向?

错误

ActiveRecord::RecordInvalid: Validation failed: Owner can't be blank

现在提供者工厂可以工作,因为它是父代。

在 PRY 工作?

shop = FactoryGirl.build(:shop)
shop.authentication_token_attributes = { token: 'test', owner: shop }
shop.save

表格

  create_table "authentication_tokens", force: :cascade do |t|
    t.string   "token",      limit: 255, null: false
    t.datetime "created_at",             null: false
    t.datetime "updated_at",             null: false
    t.integer  "owner_id",   limit: 4,   null: false
    t.string   "owner_type", limit: 255, null: false
  end

工厂

FactoryGirl.define do
  factory :shop do
    provider
    ...

    trait :with_authentication_token do
      before(:create) do |shop|
        create(:authentication_token, owner: shop)
      end
      after(:build) do |shop|
        build(:authentication_token, owner: shop)
      end
    end

    trait :inactive do
      active { false }
    end
  end
end

模型

class Shop < ActiveRecord::Base
  belongs_to :provider
  has_one :authentication_token, as: :owner, dependent: :destroy

  accepts_nested_attributes_for(:authentication_token, update_only: true)

  ...

  validates :authentication_token, presence: true, if: :shop_is_owner?

  ...

  private

  def shop_is_owner?
    return false if provider.authentication_token
    true
  end
end

class Provider < ActiveRecord::Base
  ...

  has_many :shops
  has_one :authentication_token, as: :owner, dependent: :destroy

  ...

  accepts_nested_attributes_for(:authentication_token, update_only: true)

end


class AuthenticationToken < ActiveRecord::Base
  belongs_to :owner, polymorphic: true

  validates :token,
            length: { maximum: 245 },
            presence: true,
            uniqueness: true

  validates :owner, presence: true

  validate :unique_auth_token

  def shop
    return owner if owner_type == 'Shop'
  end

  def provider
    return owner if owner_type == 'Provider'
  end

  private

  def unique_auth_token
    errors.add(:base, I18n.t('activerecord.errors.models.shop.no_auth_token_sharing')) if shop && shop.provider.authentication_token
  end
end

【问题讨论】:

    标签: ruby-on-rails factory-bot rspec-rails polymorphic-associations


    【解决方案1】:

    因此在相关模型被实例化和相关之前,您不能在任一模型上触发保存

    trait :with_authentication_token do
      before(:create) do |shop|
        create(:authentication_token, owner: shop)
      end
      after(:build) do |shop|
        build(:authentication_token, owner: shop)
      end
    end
    

    改成

    trait :with_authentication_token do
      before(:create) do |shop|
        shop.authentication_token = build(:authentication_token, owner: shop)
      end
      after(:build) do |shop|
        shop.authentication_token = build(:authentication_token, owner: shop)
      end
    end
    

    我觉得应该可以

    【讨论】:

    • @chrishough 如果有帮助,您还应该投票赞成答案.. :)
    猜你喜欢
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多