ActiveRecord:: Base не принадлежит к иерархии, спускающейся с ActiveRecord

Я пытаюсь создать плагин Rails. По большей части то, что я написал, работает. Однако есть проблема с ассоциациями. Когда я пытаюсь вызвать ассоциацию, я получаю эту ошибку:

ActiveRecord::Base doesn't belong in a hierarchy descending from ActiveRecord

В настоящий момент плагин выглядит так:

module ControlledVersioning
  module ActsAsVersionable
    extend ActiveSupport::Concern

    included do
      has_many :versions, as: :versionable

      after_create :create_initial_version
    end

    module ClassMethods
      def acts_as_versionable(options = {})

        cattr_accessor :versionable_attributes
        self.versionable_attributes = options[:versionable_attributes]
      end
    end

    private
    def create_initial_version
      version = versions.create
    end
  end
end

ActiveRecord::Base.send :include, ControlledVersioning::ActsAsVersionable

И снова сообщение об ошибке запускается всякий раз, когда я пытаюсь вызвать ассоциацию. Я использовал отладчик в обратном вызове after_create и пробовал работать:

> versions.create
*** ActiveRecord::Base doesn't belong in a hierarchy descending from ActiveRecord

> versions
*** ActiveRecord::Base doesn't belong in a hierarchy descending from ActiveRecord

> Version.new
#<Version id: nil, versionable_id: nil, versionable_type: nil>

Ответ 1

Я бы попробовал продлить активную запись в инициализаторе, а не включать его.

Инициализаторы /acts _as_versionable.rb ActiveRecord::Base.extend(ControlledVersioning::ActsAsVersionable)

Также в разработке; или в любой среде, которая перезагружает файлы, вы, вероятно, увидите ошибку, например, has been removed from the module tree but is still active. Убедитесь, что вы являетесь файлом плагина в файлах config.eager_load_path, а не на самом деле в контексте проблем.

Ответ 2

Есть несколько вещей, которые вы должны изменить в своем коде, чтобы он работал.

Во-первых, versions - это зарезервированная клавиатура от rails - вы не можете иметь отношения с этим именем - (я использовал названия versionings для того, чтобы это работало)

Кроме того, вы должны убедиться, что просто добавили версии has_many для моделей, которые хотят в acts_as_versionable есть переместите has_many :versionings, as: :versionable, class_name: 'Version' и after_create :create_initial_version внутри метода acts_as_versionable.

Вот как все вместе будет выглядеть:

module ControlledVersioning
  module ActsAsVersionable
    extend ActiveSupport::Concern

    module ClassMethods
      def acts_as_versionable(options = {})
        has_many :versionings, as: :versionable, class_name: 'Version'
        after_create :create_initial_version

        cattr_accessor :versionable_attributes
        self.versionable_attributes = options[:versionable_attributes]
      end
    end

    private

    def create_initial_version
      version = versionings.create
    end
  end
end

ActiveRecord::Base.send :include, ControlledVersioning::ActsAsVersionable

Внесение этих изменений заставило плагин работать на меня:

irb(main):003:0> Post.create!
   (0.1ms)  begin transaction
  Post Create (0.7ms)  INSERT INTO "posts" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", "2019-07-16 08:55:13.768196"], ["updated_at", "2019-07-16 08:55:13.768196"]]
  Version Create (0.2ms)  INSERT INTO "versions" ("versionable_type", "versionable_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["versionable_type", "Post"], ["versionable_id", 3], ["created_at", "2019-07-16 08:55:13.772246"], ["updated_at", "2019-07-16 08:55:13.772246"]]
   (2.0ms)  commit transaction
=> #<Post id: 3, created_at: "2019-07-16 08:55:13", updated_at: "2019-07-16 08:55:13", name: nil>
irb(main):004:0> Post.last.versionings
  Post Load (0.2ms)  SELECT  "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT ?  [["LIMIT", 1]]
  Version Load (0.2ms)  SELECT  "versions".* FROM "versions" WHERE "versions"."versionable_id" = ? AND "versions"."versionable_type" = ? LIMIT ?  [["versionable_id", 3], ["versionable_type", "Post"], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Version id: 2, versionable_type: "Post", versionable_id: 3, created_at: "2019-07-16 08:55:13", updated_at: "2019-07-16 08:55:13">]>
irb(main):005:0>