требуется, чтобы модель рельсов имела определенный метод c от модуля - PullRequest
0 голосов
/ 30 марта 2020

У меня есть модуль, который определяет некоторые методы и который я включаю в некоторые модели Rails. Я хочу, чтобы модели, в которые включен модуль, имели определенные определенные методы c (как если бы я хотел, чтобы они реализовали интерфейс).

Однако проблема возникает, когда я хочу, чтобы модели имели метод это оказывается атрибутом, который уже определена активной записью.

Мой код выглядит следующим образом:

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

Метод name класса Supplier фактически переопределяется методом модуль Mod, который не является поведением, которое я хочу.

1 Ответ

0 голосов
/ 30 марта 2020
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-включено объясняет «Оценивать данный блок в контексте базового класса, чтобы вы могли писать здесь макросы классов. Когда вы определяете более одного включенного блока, он вызывает исключение." Обычно он используется для определения отношений, областей действия, проверок

Связанный и полезный вопрос и ответ Stackoverflow: Ruby модулей - в том числе завершить блок , в частности, { ссылка }

=======

Рабочий пример, локально:

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
...