使用模型的后代动态生成范围
Dynamically Generating Scopes with Descendants of a Model
我在为我的 STI 模型动态生成范围时遇到问题。这是模型结构:
app/models/unit.rb
class Unit < ApplicationRecord
def self.types
descendants.map(&:name)
end
# Dynamically generate scopes for STI-related models
types.each do |type|
scope type.tableize.to_sym, -> { where(type: type) }
end
end
app/models/units/academy.rb
class Academy < Unit
end
app/models/units/faculty.rb
class Faculty < Unit
end
config/environment/development.rb
config.eager_load = false
# Enable auto-load only for these files
Rails.application.reloader.to_prepare do
Dir[
Rails.root.join('app', 'models', '**', '*.rb')
].each { |file| require_dependency file }
end
当我在开发模式下进入 Rails 控制台时,我可以像这样轻松地检查单元类型:
Unit.types
["Academy", "Faculty"]
但是我无法达到预期的范围(例如 Unit.faculties、Unit.academies),因为 Rails 无法为我生成范围,因为它获得 'types' 作为空数组。我的意思是单元模型的这一部分:
types.each do |type|
scope type.tableize.to_sym, -> { where(type: type) }
end
我可以从控制台检查类型,即使在开发模式下也是如此,但是当涉及到动态生成范围时,类型返回一个空数组。
问题是后代 类 没有实例化。以下解决方法将帮助您实现您的目标:
def self.types
ActiveRecord::Base.connection.tables.map {|t| t.classify.constantize rescue nil}.compact
descendants.map(&:name)
end
但就我个人而言,我认为您根本不需要这些范围,因为在后代 类 上调用 all
将提供查询:
Faculty.all
等同于 Unit.where(type: "Faculty")
Academy.all
等同于 Unit.where(type: "Academy")
我在为我的 STI 模型动态生成范围时遇到问题。这是模型结构:
app/models/unit.rb
class Unit < ApplicationRecord
def self.types
descendants.map(&:name)
end
# Dynamically generate scopes for STI-related models
types.each do |type|
scope type.tableize.to_sym, -> { where(type: type) }
end
end
app/models/units/academy.rb
class Academy < Unit
end
app/models/units/faculty.rb
class Faculty < Unit
end
config/environment/development.rb
config.eager_load = false
# Enable auto-load only for these files
Rails.application.reloader.to_prepare do
Dir[
Rails.root.join('app', 'models', '**', '*.rb')
].each { |file| require_dependency file }
end
当我在开发模式下进入 Rails 控制台时,我可以像这样轻松地检查单元类型:
Unit.types
["Academy", "Faculty"]
但是我无法达到预期的范围(例如 Unit.faculties、Unit.academies),因为 Rails 无法为我生成范围,因为它获得 'types' 作为空数组。我的意思是单元模型的这一部分:
types.each do |type|
scope type.tableize.to_sym, -> { where(type: type) }
end
我可以从控制台检查类型,即使在开发模式下也是如此,但是当涉及到动态生成范围时,类型返回一个空数组。
问题是后代 类 没有实例化。以下解决方法将帮助您实现您的目标:
def self.types
ActiveRecord::Base.connection.tables.map {|t| t.classify.constantize rescue nil}.compact
descendants.map(&:name)
end
但就我个人而言,我认为您根本不需要这些范围,因为在后代 类 上调用 all
将提供查询:
Faculty.all
等同于 Unit.where(type: "Faculty")
Academy.all
等同于 Unit.where(type: "Academy")