ruby - ruby 中的可配置改进
问题描述
我想用配置对象修补现有库的一部分:
module Library
class A
end
class B
end
end
module Config
def config(&block)
@config ||= block&.call
end
end
module Patch
refine Library::A.singleton_class do
extend Config
config { "my for A" }
end
refine Library::B.singleton_class do
extend Config
config { "my for B" }
end
end
Library::A
应该有一些预定义的配置,并且Library::B
应该有自己的配置。不幸的是,这会引发错误:
using Patch
Library::A.config
=> undefined method `config' for Library::A:Class (NoMethodError)
我想我不明白在这种情况下如何进行改进。但是有没有办法实现这样的目标?
解决方案
这是我的解决方案,基本上include Config
是Patch
为了能够在类级别定义配置,然后include
是Patch
自身到精炼类(Library::A 和 Library::B),以便能够访问定义的配置。
module Config
def self.included(base)
class << base
def refinement(clazz, patch=self, &block)
$predefined_configs ||= Hash.new
$predefined_configs[clazz] ||= Hash.new
block&.call($predefined_configs[clazz])
refine clazz.singleton_class do
include patch
end
end
end
end
def config
$predefined_configs[self].tap do |_config|
# reuse common configs
_config.merge!({
lang: "ruby"
})
end
end
end
然后
module Library
class A; end
class B; end
end
module Patch
include Config
refinement(Library::A) do |_config|
_config[:name] = "my for A"
end
refinement(Library::B) do |_config|
_config[:name] = "my for B"
end
end
class LoadConfig
using Patch
puts Library::A.config # {:name=>"my for A", :lang=>"ruby"}
end
puts Library::A.config # error
using Patch
puts Library::B.config # {:name=>"my for B", :lang=>"ruby"}
推荐阅读
- python - 尝试流式传输电报媒体并在网页中播放
- python - 函数作为另一个函数的参数
- azure-ad-b2c - 用户登录 App Azure AD B2C 后访问配置文件编辑策略时再次显示登录屏幕
- regex - awk 函数在 csv 中使用正则表达式修改多个列
- java - 不兼容的类型:在 Flutter 中 Activity 无法转换为 AppCompatActivity
- html - 汉堡菜单 css 悬停无法正常工作
- python - Python 搜索文件并查找和替换值
- php - 如何使用 PHP 将联系人添加到 google 联系人 api v3 中的组
- python - Rasa init 给出错误:memoizationPolicy
- java - 如何从颤动中正确调用android本机代码(android/IOS)?