ruby-on-rails - 不能在前置模块中使用实例变量

标签 ruby-on-rails ruby module prepend

我希望能够将我的模块包含在 ActiveRecord::Base 中,以便 has_folder_attachments 方法可用于我的 Rails AR 类。

我这样做是为了扩展原始模块的功能以支持 AR Hook ;但是变量 @physical_path@dice 都是 nil,我不明白为什么。

module FolderAttachments
  module ClassMethods
    def has_folder_attachments(physical_path, excludes: [])
      @physical_path = physical_path
      super
    end 
  end  

  def self.prepended(base)
    class << base
      prepend ClassMethods
    end  
  end  

  attr_reader :physical_path
end

module ActiveRecord
  class Base
    prepend FolderAttachments

    attr_reader :dice

    # This should run after the module method
    def self.has_folder_attachments(*args)
      @dice = true
    end
  end
end

class Damned < ActiveRecord::Base
  has_folder_attachments :for_real
end

damn = Damned.new
puts damn.physical_path # => nil
puts damn.dice          # => nil

最佳答案

在使用这两个变量时,您正在混合实例和(元)类上下文。这两个变量都在类上下文中运行的方法中设置它们的值(更准确地说是在 metaclass 的上下文中)。因此,您无法在实例上下文中访问这些变量(及其 attr_reader)。

要使 attr_reader 正常工作,您必须将它们移动到类上下文并从那里访问它们:

module FolderAttachments
  module ClassMethods
    ...
    attr_reader :physical_path
  end
end

module ActiveRecord
  class Base
    ...
    class << self
      attr_reader :dice
    end
  end
end

damn = Damned.new
damn.class.physical_path # => :for_real
damn.class.dice          # => true

或者您还可以添加委托(delegate)给类级读取器的实例级读取器,以便您也可以在实例上下文中访问它们:

module FolderAttachments
  module ClassMethods
    ...
    attr_reader :physical_path
  end

  def physical_path
    self.class.physical_path
  end
end

module ActiveRecord
  class Base
    ...
    class << self
      attr_reader :dice
    end

    def dice
     self.class.dice
    end
  end
end

damn = Damned.new
damn.physical_path # => :for_real
damn.dice          # => true

关于ruby-on-rails - 不能在前置模块中使用实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43699366/

相关文章:

ruby-on-rails - Rails 无法将不允许的参数转换为散列

ruby - 使用 charlock_holmes gem 的 undefined symbol

python - self.direction = pygame.Vector2(1, 0)#Vector2(1,0) ;属性错误: 'module' object has no attribute 'Vector2'

尽管已安装 Python 模块但未被检测到

ruby-on-rails - 数据旁边的 CSV header - Rails Import

ruby-on-rails - has_many 通过具有唯一来源的多个模型

ruby - Ruby 的 Enumerator 对象如何在内部迭代器上进行外部迭代?

python - 如何通过 conda 安装我自己的 python 模块(包)并观察它的变化

ruby-on-rails - 如何覆盖 lib/spree/search/base.rb

ruby-on-rails - 使用accepts_nested_attributes_for 和denefit_exposure 未设置关联ID