Ruby on Rails中Concern定义的attr_accessor无法访问如何解决
问题核心原因
你代码中定义的attr_accessor :foo被放在了控制器类的单例类作用域下,属于类级别属性,仅能在控制器类的上下文调用。而index是控制器的实例方法,运行时上下文是控制器实例,自然无法直接访问类层面的属性。
解决方法
根据你的实际使用场景,可选择以下两种方案:
方案1:保留类级别共享属性(所有控制器实例共享同一个foo值)
如果你的需求是foo值全局统一,所有该控制器的请求都共用同一个值,只需在Concern中新增实例层的方法代理即可:
修改app/controllers/concerns/foobar_concern.rb代码如下:
module FoobarConcern extend ActiveSupport::Concern included do class << self attr_accessor :foo end # 给实例层添加存取方法代理,指向类的同名方法 delegate :foo, :foo=, to: :class end class_methods do def test_method(bar) self.foo = bar end end end
修改后你原有控制器index方法中的self.foo、直接调用foo都可以正常获取到值。
方案2:使用实例级别独立属性(不同请求的foo值互不干扰)
如果你的需求是每个请求对应的控制器实例有独立的foo值,将属性定义调整到实例层面即可:
修改app/controllers/concerns/foobar_concern.rb代码如下:
module FoobarConcern extend ActiveSupport::Concern included do # 直接定义实例层面的存取方法 attr_accessor :foo end class_methods do def test_method(bar) # 给所有实例设置默认foo值 define_method :initialize do |*args| super(*args) self.foo = bar end end end end
修改后控制器实例可以直接调用foo相关方法,且不同请求的属性值互相独立,不会串值。
内容的提问来源于stack exchange,提问作者Dean
相关产品推荐
相关产品推荐

