3

我正在编写一些装饰器来覆盖 Rails 引擎,如此所述。我正在尝试从引擎向一个类添加一个简单的方法,这是我的代码:

# app/decorators/models/my_engine/user_decorator.rb

MyEngine::User.class_eval do
  def self.find_by_name_or_mis_id str
    where("CONCAT(#{table_name}.firstname, ' ', #{table_name}.surname) LIKE CONCAT('%', :s, '%') OR mis_id = :s", { s: str })
  end
end

我的应用程序找不到该方法,并在 rails 控制台中尝试对其进行测试:

# rails c
MyEngine::User.find_by_name_or_mis_id "John"
NoMethodError: undefined method `find_by_name_or_mis_id' for #<Class:0x007fcb85a45580>

我可以通过require '/models/my_engine/user_decorator'在控制台上进行操作来使其工作,为什么 rails 没有拾取我的装饰器?

4

4 回答 4

6

好吧,经过相当多的膛线,事实证明似乎没有自动加载。需要的是(在他们将其提取到此 gem之前从forem repo中提取):

# MyEngine
# lib/my_engine/engine.rb

module MyEngine
  class Engine < ::Rails::Engine
    isolate_namespace MyEngine

    config.to_prepare do
      Dir.glob(Rails.root + "app/decorators/**/*_decorator*.rb").each do |c|
        require_dependency(c)
      end
    end
  end
end

我将在文档上提出一张票,以便他们可以包含此信息,因为他们进入了有关装饰器的一些细节,但没有解释您如何实际加载它们(假设这一切都是为您处理的)。

更新:我确实提出了一张票,并且相应地更新了指南。

于 2013-05-16T15:52:26.643 回答
2
config.to_prepare do
  # Load application's model / class decorators
  Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
    Rails.configuration.cache_classes ? require(c) : load(c)
  end
end
于 2015-11-28T15:31:12.567 回答
1

很抱歉碰到一个老问题。我对装饰器宝石有一些问题。另一种方法是activesupport-decorators

于 2014-03-04T13:09:22.450 回答
0

require_dependency对于在没有内置装饰器功能的情况下也适用于 Rails 引擎的灵活替代方案,请考虑镜像您要覆盖的类的文件路径,并在自定义之前使用 require_dependency 来要求原始类。

这种技术不使用装饰器。相反,它会在同名文件中重新打开该类:

# File: app/models/my_engine/user.rb

# Load the original class definition from the engine:
require_dependency "#{MyEngine::Engine.root}/app/models/my_engine/user"

# Open class to modify it:
module MyEngine
  class User
    def self.find_by_name_or_mis_id(str)
      where("CONCAT(#{table_name}.firstname, ' ', #{table_name}.surname) LIKE CONCAT('%', :s, '%') OR mis_id = :s", { s: str })
    end
  end
end
于 2016-05-18T17:09:57.903 回答