如何在ActiveSupport::Concern中隐藏部分内部常量不对外暴露
实现方案
完全可以实现,Ruby 2.1及以上版本原生支持私有常量声明,无需额外扩展即可满足需求。
方案1:使用private_constant关键字(推荐)
直接在Concern模块内对需要隐藏的常量声明为私有即可,代码示例如下:
module MyConcern extend ActiveSupport::Concern ## 私有常量 PRIVATE_FOO = 'foo' PRIVATE_BAR = 'bar' # 标记为私有常量,禁止外部访问 private_constant :PRIVATE_FOO, :PRIVATE_BAR ## 公开常量 PUBLIC_FOOBAR = PRIVATE_FOO + PRIVATE_BAR end class MyClass < ApplicationRecord include MyConcern PRIVATE_FOO # 抛出 NameError: private constant MyConcern::PRIVATE_FOO referenced PRIVATE_BAR # 抛出 NameError: private constant MyConcern::PRIVATE_BAR referenced PUBLIC_FOOBAR # 正常返回 "foobar" end
该方案同时会拦截直接通过模块访问私有常量的行为:MyConcern::PRIVATE_FOO同样会抛出NameError,安全性更高。
兼容低版本Ruby的备选方案
如果运行环境Ruby版本低于2.1,可以将私有常量封装到Concern内部的私有嵌套模块中:
module MyConcern extend ActiveSupport::Concern # 私有嵌套模块,外部无法访问 module PrivateImpl PRIVATE_FOO = 'foo' PRIVATE_BAR = 'bar' end private_constant :PrivateImpl PUBLIC_FOOBAR = PrivateImpl::PRIVATE_FOO + PrivateImpl::PRIVATE_BAR end
注意事项
不要将私有常量定义在included/class_methods等块内,否则常量会被直接定义到引入类的上下文,无法做到访问限制。
内容的提问来源于stack exchange,提问作者Ashbury
相关产品推荐
相关产品推荐

