我有一个Active Record模型(清单),该模型应该将一些属性存储在数据库中,而其他一些属性将存储在区块链(以太坊)中。
理想情况下,当开发人员执行model_record.save
时,应该重写活动记录保存方法,首先将适当的属性保存在区块链中,然后再进行常规的活动记录保存。此过程适用于大多数其他方法,例如.update
,.destroy
,.create
。
通过在模型中添加宏级别声明以将区块链属性与常规活动记录列区分开来实现以下目的
class Listing < ApplicationRecord
include BlockchainRecord
self.table_name = "listings"
blockchain_properties :parcel_no,
:description
end
模块BlockchainRecord
也已包含在模型中,并包含如下所示的方法
module BlockchainRecord
extend ActiveSupport::Concern
...............
class_methods do
def blockchain_properties(*props)
@@blockchain_attributes = props
define_method :blockchain_attributes do
props
end
props.each do |prop|
define_method prop do
if self.instance_variable_defined?("@#{prop}")
self.instance_variable_get("@#{prop}")
else
if self.address
val = self.contract.call.send("#{prop}")
self.instance_variable_set("@#{prop}", val)
val
else
nil
end
end
end
# Setter methods
define_method "#{prop}=" do |arg|
self.instance_variable_set("@#{prop}", arg)
end
end
end
def new(props = {})
model_record = super(props.except(blockchain_attributes))
blockchainProps = props.slice(*blockchain_attributes)
blockchainProps.each do |k, v|
model_record.send("#{k}=", v)
end
return model_record
end
end
def save
if self.address
blockchain_attributes.each do |prop|
self.contract.transact_and_wait.send("set_#{prop}", self.send("#{prop}"))
sleep(2)
end
super
else
# in case we call Class.new then Object.save
contract = Ethereum::Contract.create(file: self.class.contract_file_path)
key = Eth::Key.new(priv: ENV["PRIVATE_KEY"])
contract.key = key
self.address = contract.deploy_and_wait(*(self.attributes.slice(*blockchain_attributes).values))
super
end
end
end
当完成一个活动记录对象的保存,然后再尝试进行类似Model.count
或Model.all
的操作时,就会发生此问题。
例如,如果我这样做了,
l = Listing.new(parcel_no: 1234, description: "...", registration_section: "...")
然后保存记录l.save
,该记录将正确存储区块链属性(parcel_no和description),然后调用ActiveRecord提供的.save
将其余属性保存到数据库。
但是,当我进行类似Listing.count
的后续调用时,失败并显示以下错误消息 NoMethodError:Listing:Class的未定义方法计数,并且当我检查{的祖先时{1}}我得到Listing
,这意味着它不再从活动记录库中继承
为什么在模块中覆盖该activerecord .save方法会导致[Listing, ActiveSupport::ToJsonWithActiveSupportEncoder, Object, PP::ObjectMixin, MakeMakefile, ActiveSupport::Dependencies::Loadable, JSON::Ext::Generator::GeneratorMethods::Object, ActiveSupport::Tryable, Kernel, BasicObject]
模型不再继承自ActiveRecord :: Base以及如何解决?