Rails 基于模型名称的命名空间问题
Rails namespacing concerns based on model name
我正在寻找针对特定于模型的某些功能子集的关注点。
我引用了 here 并遵循了这个模式
module ModelName::ConcernName
extend ActiveSupport::Concern
included do
# class macros
end
# instance methods
def some_instance_method
end
module ClassMethods
# class methods here, self included
end
end
但是,当我尝试启动服务器时会导致以下错误
Circular dependency detected while autoloading constant ModelName::ConcernName
我想知道对模型的某些子集函数进行关注的最佳方法是什么。
编辑
提供型号代码:
路径:app/models/rent.rb
现在我的模型中有很多检查逻辑
class Rent < ActiveRecord::Base
def pricing_ready?
# check if pricing is ready
end
def photos_ready?
# check if photo is ready
end
def availability_ready?
# check if availability setting is ready
end
def features_ready?
# check if features are set
end
end
我想分开关注
class Rent < ActiveRecord::Base
include Rent::Readiness
end
并按命名空间组织关注点
路径:app/models/concerns/rent/readiness.rb
module Rent::Readiness
extend ActiveSupport::Concern
included do
# class macros
end
# instance methods
def pricing_ready?
# check if pricing is ready
end
...
module ClassMethods
# class methods here, self included
end
end
现在如果我用 app/models/concerns/rent_readiness.rb
中的路径 class RentReadiness
就可以正常工作了
Rails 使用 activesupport 加载 classes 和模块,因为它们是通过根据 class 或模块名称推断文件路径来定义的,这是作为 Ruby 解析器加载您的文件并遇到一个尚未加载的新常量。在您的情况下,Rent
模型被解析为 Rent::Readlines
引用,此时 activesupport 开始寻找与名称匹配的 rent/readlines.rb
代码文件。然后这个文件被 ruby 解析,但是在第一行,仍然未加载的 Rent
class 被引用,这会触发 activesupport 关闭并寻找匹配的代码文件名字.
您可以将其范围限定为 Rents
并放置到 concerns/rents/readiness.rb
:
module Rents
module Readiness
extend ActiveSupport::Concern
included do
# class macros
end
end
end
在模型中:
class Rent < ActiveRecord::Base
include Rents::Readiness
end
您只需将包含模型特定问题的文件夹从 concerns
移动到 models
即可使其正常工作。所以,你会:
models/
rent.rb
rent/
readiness.rb
我喜欢这种使用模型作为其关注点的名称空间的约定,因为它可以让您从代码中删除一些冗余:
- 由于您是在模型 class 中定义关注点,因此您可以在模型中编写
include Readiness
而不是 include Rent::Readiness
定义关注点时,可以使用module Rent::Readiness
代替
class Rent < ApplicationRecord
module Readiness
...
这将是解决您在问题中提到的循环依赖问题的另一种方法。
我正在寻找针对特定于模型的某些功能子集的关注点。 我引用了 here 并遵循了这个模式
module ModelName::ConcernName
extend ActiveSupport::Concern
included do
# class macros
end
# instance methods
def some_instance_method
end
module ClassMethods
# class methods here, self included
end
end
但是,当我尝试启动服务器时会导致以下错误
Circular dependency detected while autoloading constant ModelName::ConcernName
我想知道对模型的某些子集函数进行关注的最佳方法是什么。
编辑
提供型号代码: 路径:app/models/rent.rb
现在我的模型中有很多检查逻辑
class Rent < ActiveRecord::Base
def pricing_ready?
# check if pricing is ready
end
def photos_ready?
# check if photo is ready
end
def availability_ready?
# check if availability setting is ready
end
def features_ready?
# check if features are set
end
end
我想分开关注
class Rent < ActiveRecord::Base
include Rent::Readiness
end
并按命名空间组织关注点 路径:app/models/concerns/rent/readiness.rb
module Rent::Readiness
extend ActiveSupport::Concern
included do
# class macros
end
# instance methods
def pricing_ready?
# check if pricing is ready
end
...
module ClassMethods
# class methods here, self included
end
end
现在如果我用 app/models/concerns/rent_readiness.rb
RentReadiness
就可以正常工作了
Rails 使用 activesupport 加载 classes 和模块,因为它们是通过根据 class 或模块名称推断文件路径来定义的,这是作为 Ruby 解析器加载您的文件并遇到一个尚未加载的新常量。在您的情况下,Rent
模型被解析为 Rent::Readlines
引用,此时 activesupport 开始寻找与名称匹配的 rent/readlines.rb
代码文件。然后这个文件被 ruby 解析,但是在第一行,仍然未加载的 Rent
class 被引用,这会触发 activesupport 关闭并寻找匹配的代码文件名字.
您可以将其范围限定为 Rents
并放置到 concerns/rents/readiness.rb
:
module Rents
module Readiness
extend ActiveSupport::Concern
included do
# class macros
end
end
end
在模型中:
class Rent < ActiveRecord::Base
include Rents::Readiness
end
您只需将包含模型特定问题的文件夹从 concerns
移动到 models
即可使其正常工作。所以,你会:
models/
rent.rb
rent/
readiness.rb
我喜欢这种使用模型作为其关注点的名称空间的约定,因为它可以让您从代码中删除一些冗余:
- 由于您是在模型 class 中定义关注点,因此您可以在模型中编写
include Readiness
而不是include Rent::Readiness
定义关注点时,可以使用
module Rent::Readiness
代替class Rent < ApplicationRecord module Readiness ...
这将是解决您在问题中提到的循环依赖问题的另一种方法。