Rails 模型指的是新的假模型
Rails model referring to new fake model
我有以下模型结构,我在其中存储了 Books 和 SellingInfo(代表售前和售后成本):
class Books < ApplicationRecord
STATUSES = %w[planned purchased].freeze
has_many :selling_infos, dependent: :destroy
end
class SellingInfo < ApplicationRecord
belongs_to :book
end
由于 ActiveAdmin 的要求,我想与模型建立新关系,该模型与 selling_infos
table(相同的列、类型等)相同,但我只会使用它当 Book.status == 'purchased'
。为了不使数据库超载,我不想创建新模型,假设 purchased_selling_info
,具有相同的数据结构,但创建某种 'fake model' 并将其用作 purchased_selling_info
。
我正在尝试将如下内容添加到 Book 模型中:
# models/book.rb
has_one :purchased_selling_info,
-> { where(status: 'purchased') },
class_name: 'SellingInfo',
dependent: :destroy
但是当我尝试检查它是否在 rails 控制台中工作时,我收到一个错误:
2.7.2 :009 > Book.purchased_selling_info.size
NoMethodError (undefined method `purchased_selling_info' for #<Class:0x00007f9916f33200>)
将具有不同行为的记录存储在一个 table 中的解决方案是 Single Table Inheritance。通过添加 type
列,您可以拥有不同的关联:
class Book < ApplicationRecord
has_many :selling_infos, dependent: :destroy
end
class PurchasedBook < Book
has_one :purchased_selling_info,
class_name: 'SellingInfo',
dependent: :destroy
end
当您从数据库中加载记录时,ActiveRecord 会读取继承列(默认情况下为 type
)并将初始化 class。
如果您不想使用 STI,您可以通过 custom validations or association callbacks.
限制 purchased_selling_info
的创建
class SellingInfo
validates :validates_is_purchased, if: ->{ |si| si.purchased? }
def validates_is_purchased
errors.add(:book, 'wrong book type')
end
end
您目前正在做的事情将无法工作,因为:
- 将 lambda 添加到关联只是将过滤器应用于关联。关联是 class 级别的,您不能使它们依赖于实例的属性。
Book.purchased_selling_info.size
给出 NoMethod 错误,因为您在 class. 上调用实例方法
In order not to overload the database I don't want to create new model, let's say purchased_selling_info, with the same data structure but create some kind of 'fake model' and use it as purchased_selling_info.
您应该仔细权衡“使数据库过载”与 hacky 解决方案增加的复杂性和维护成本。对我来说,这听起来像是一个过早优化的案例。
我有以下模型结构,我在其中存储了 Books 和 SellingInfo(代表售前和售后成本):
class Books < ApplicationRecord
STATUSES = %w[planned purchased].freeze
has_many :selling_infos, dependent: :destroy
end
class SellingInfo < ApplicationRecord
belongs_to :book
end
由于 ActiveAdmin 的要求,我想与模型建立新关系,该模型与 selling_infos
table(相同的列、类型等)相同,但我只会使用它当 Book.status == 'purchased'
。为了不使数据库超载,我不想创建新模型,假设 purchased_selling_info
,具有相同的数据结构,但创建某种 'fake model' 并将其用作 purchased_selling_info
。
我正在尝试将如下内容添加到 Book 模型中:
# models/book.rb
has_one :purchased_selling_info,
-> { where(status: 'purchased') },
class_name: 'SellingInfo',
dependent: :destroy
但是当我尝试检查它是否在 rails 控制台中工作时,我收到一个错误:
2.7.2 :009 > Book.purchased_selling_info.size
NoMethodError (undefined method `purchased_selling_info' for #<Class:0x00007f9916f33200>)
将具有不同行为的记录存储在一个 table 中的解决方案是 Single Table Inheritance。通过添加 type
列,您可以拥有不同的关联:
class Book < ApplicationRecord
has_many :selling_infos, dependent: :destroy
end
class PurchasedBook < Book
has_one :purchased_selling_info,
class_name: 'SellingInfo',
dependent: :destroy
end
当您从数据库中加载记录时,ActiveRecord 会读取继承列(默认情况下为 type
)并将初始化 class。
如果您不想使用 STI,您可以通过 custom validations or association callbacks.
限制purchased_selling_info
的创建
class SellingInfo
validates :validates_is_purchased, if: ->{ |si| si.purchased? }
def validates_is_purchased
errors.add(:book, 'wrong book type')
end
end
您目前正在做的事情将无法工作,因为:
- 将 lambda 添加到关联只是将过滤器应用于关联。关联是 class 级别的,您不能使它们依赖于实例的属性。
Book.purchased_selling_info.size
给出 NoMethod 错误,因为您在 class. 上调用实例方法
In order not to overload the database I don't want to create new model, let's say purchased_selling_info, with the same data structure but create some kind of 'fake model' and use it as purchased_selling_info.
您应该仔细权衡“使数据库过载”与 hacky 解决方案增加的复杂性和维护成本。对我来说,这听起来像是一个过早优化的案例。