【问题标题】:redefining gem method in rails model not working在 Rails 模型中重新定义 gem 方法不起作用
【发布时间】:2014-02-27 18:53:15
【问题描述】:

所以我有一个 gem,其中包含一些活动记录模型,这些模型被我们平台上的多个应用程序使用。我们有一个常量来定义一个“类型”列表,这些“类型”在几个不同的应用程序上是不同的。

# in the gem
class MyModel < ActiveRecord::Base
  TYPES = ["A Type", "Another Type"]
end

在应用程序代码中重新定义此常量将为已初始化的常量生成警告。因此,由于它不是真正恒定的,因此我决定将其重构为类方法。

# gem
class MyModel < ActiveRecord::Base
  def self.types
    []
  end
end

# application a
class MyModel < ActiveRecord::Base
  def self.types
    ["A Type", "D Type"]
  end
end

# application b
class MyModel < ActiveRecord::Base
  def self.types
    ["B Type", "C Type"]
  end    
end

但是,在 App A 或 B 中访问 MyModel.types 时,types 是 []。这个问题以及其他一些问题让我得出结论,gem 是在加载 rails 应用程序之后加载的,而我的假设恰恰相反。

处理此类不同情况的最佳方法是什么?

【问题讨论】:

    标签: ruby-on-rails ruby activerecord gem


    【解决方案1】:

    在您的应用程序中执行此操作

    在您的config/initializers/ 中创建一个文件,并将此代码添加到您的两个应用中

    MyModel.instance_eval do
      def types
        ["A Type", "D Type"]
      end
    end
    

    MyModel.class_eval do
      def self.types
        ["A Type", "D Type"]
      end
    end
    

    【讨论】:

    • @apneadiving:instance_eval 是对的。它将方法添加到 MyModel 的 eigenclass
    • 老实说,我希望避免这种方法,因为其中一个应用程序非常大,我想将代码保留在可预测的位置,但我决定在本地类重新打开并执行初始化方式。谢谢
    【解决方案2】:

    您必须从引擎中明确要求初始类,这将确保加载它。 开发中有时并非如此(例如autoload

    require YourEngine::Engine.root.join('app/models/your_namespace/my_model')
    
    class MyModel  #no inheritance here, we just reopen an existing class, right?
       def self.types
         [] #override it as you like
       end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-23
      • 2012-02-06
      • 2019-09-08
      • 1970-01-01
      • 2012-03-13
      • 1970-01-01
      • 2015-11-01
      • 1970-01-01
      相关资源
      最近更新 更多