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>