Как сделать простой рубиновый объект, который можно присвоить как активная запись ассоциации
У меня есть класс Audit
, который поддерживается ActiveRecord.
class Audit < ActiveRecord::Base
belongs_to :user, polymorphic: true
end
У меня есть класс User
, который представляет собой простой объект ruby с некоторой функциональностью ActiveModel. Это не модель базы данных, потому что мои пользователи фактически хранятся в другой базе данных и обслуживаются через API.
class User
include ActiveModel::Conversion
include ActiveModel::Validations
extend ActiveModel::Naming
def self.primary_key
'id'
end
def id
42
end
def persisted?
false
end
end
Я пытаюсь назначить пользователя для такого аудита:
audit = Audit.new
audit.user = User.new
audit.save!
С точки зрения данных, это должно работать нормально. Чтобы определить полиморфную ассоциацию, нам нужно разделить значения на два столбцы в таблице аудита. Мы можем установить audits.user_id
в значение 42
и audits.user_type
в строку "пользователь".
Однако я попал в исключение:
undefined method `_read_attribute' for #<User:0x007f85faa49520 @attributes={"id"=>42}> (NoMethodError)
active_record/associations/belongs_to_polymorphic_association.rb:13:in `replace_keys'
Я проследил это до источника ActiveRecord
, и он, кажется, определен здесь. К сожалению, тот факт, что это ActiveRecord
, а не ActiveModel
, означает, что я не могу включить этот микс в свой класс.
Я попытался определить свой собственный метод _read_attribute
, но я спускаюсь в кроличью нору необходимости переопределять все больше и больше функций ActiveRecord например, AttributeSet и так далее.
Audit#user_type
и Audit#user_id
. Однако это неудовлетворительно, потому что на самом деле мне пришлось бы раскошелиться на драгоценный камень и отредактировать его, чтобы сделать это.
Как я могу изменить свой класс пользователя, чтобы я мог чисто назначить его аудиту.
P.S.Вот пример приложения , так что вы можете попробовать это самостоятельно.
1 ответ:
Вместо того, чтобы взламывать все глубже и глубже для репликации функциональности
ActiveRecord
, Вы можете рассмотреть возможность фактического наследования отActiveRecord::Base
вместо включенияActiveModel
. Единственное ограничение-у вас нет таблицы. Для этого есть драгоценный камень:Этот класс работает с вашим примером приложения:
require 'active_record' require 'activerecord-tableless' class User < ActiveRecord::Base has_no_table # required so ActiveRecord doesn't try to create a new associated # User record with the audit def new_record? false end def id 42 end end