【问题标题】:require a rails model to have a specific method from a module要求 Rails 模型具有来自模块的特定方法
【发布时间】:2020-03-29 21:18:23
【问题描述】:

我有一个模块,它定义了一些方法,并包含在一些 Rails 模型中。我希望包含模块的模型定义一些特定的方法(好像我希望它们实现一个接口)。

但是,当我希望模型有一个方法,结果证明是活动记录已经定义的属性时,问题就出现了。

我的代码如下:

Module Mod
  included do
    # some code...
    # require some methods to be implemented by including class
    def do_x
      raise('not implemented, please override me')
    end

    def name
      raise('not implemented, please override me')
    end
  end
end

class Supplier < ApplicationRecord
  # already has a name attribute
  include Mod

  # this overrides do_x of mod
  def do_x
    # some code...
  end
end

Supplier 类的 name 方法实际上被模块 Mod 的方法覆盖,这不是我想要的行为。

【问题讨论】:

    标签: ruby-on-rails ruby multiple-inheritance


    【解决方案1】:
    Module Mod
      # some code...  (within an included block)
      # require some methods to be implemented by including class
      def do_x
        raise('not implemented, please override me')
      end
    
      def name
        raise('not implemented, please override me')
      end
    end
    
    class Supplier < ApplicationRecord
      include Mod
    
      # this overrides do_x of mod
      def do_x
        # some code...
      end
    end
    

    included 块中删除那些似乎对我有用。

    https://api.rubyonrails.org/classes/ActiveSupport/Concern.html#method-i-included 解释“在基类的上下文中评估给定块,以便您可以在此处编写类宏。当您定义多个包含块时,它会引发异常。”它通常用于定义关系、范围、验证

    一个相关且有用的 Stackoverflow 问题和答案:Ruby modules - included do end block ,具体来说,https://stackoverflow.com/a/28009847/2526423

    =======

    本地工作示例:

    irb(main):070:0> Author.create!
       (0.1ms)  SELECT sqlite_version(*)
       (0.1ms)  begin transaction
      Author Create (0.5ms)  INSERT INTO "authors" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", "2020-03-29 22:06:28.202124"], ["updated_at", "2020-03-29 22:06:28.202124"]]
       (0.8ms)  commit transaction
    => #<Author id: 2, name: nil, year: nil, created_at: "2020-03-29 22:06:28", updated_at: "2020-03-29 22:06:28", uid: nil>
    irb(main):071:0> author.name
    => nil
    irb(main):072:0> author.do_x
    class: do_x
    => nil
    

    app/models/author.rb

    require 'do_x_mod'
    
    class Author < ApplicationRecord
      include DoXMod
    
      def do_x
        puts "class: do_x"
      end
    end
    

    lib/do_x_mod.rb

    module DoXMod
      # included do
        # some code...
        # require some methods to be implemented by including class
        def do_x
          puts "module: do_x"
          raise('not implemented, please override me')
        end
    
        def name
          puts "module: name"
          raise('not implemented, please override me')
        end
      # end
    end
    

    【讨论】:

    • do_xname 放在包含的块之外并没有解决我的问题。当我尝试在 Supplier 实例上调用 name 方法时,它仍然会引发异常。
    • @AbdelrahmanAbdelnabi 你能提供供应商模型和迁移吗?以及确切的堆栈跟踪?你在哪个版本的 Rails 上?您是否同意所提供的示例(尽管名称不同)具有预期的行为?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多