我正在尝试在我的应用中构建继承。
事实上,我很简单,我有几个模型,其中一些需要“归档”,它只是意味着我将数据从我的数据库公共原理图移动到归档原理图(相同的数据库)。
每个模型都有一个方法'save'itself'OnArchive by example:
def saveContactArchive(contact)
record = ArchContacts.new
record.id=contact.id
record.information_id=contact.information_id
record.is_internal = contact.is_internal if (contact.is_internal != nil)
record.type_contact_id = contact.type_contact_id if (contact.type_contact_id != nil)
record.user_id = contact.user_id if (contact.user_id != nil)
record.info_readed = contact.info_readed if (contact.info_readed != nil)
record.not_received = contact.not_received if (contact.not_received != nil)
record.society_name = contact.society_name if (contact.society_name != nil)
record.person_name = contact.person_name if (contact.person_name != nil)
record.email = contact.email if (contact.email != nil)
record.receipt = contact.receipt if (contact.receipt != nil)
record.receipt_confirmed = contact.receipt_confirmed if (contact.receipt_confirmed != nil)
record.created_at = contact.created_at if (contact.created_at != nil)
record.updated_at = contact.updated_at if (contact.updated_at != nil)
id = contact.id
if (!existOnArchive(id))
return record.save
else
return true
end
end
并且有些模型以示例方式保存了'arrayOf'OnArchive:
def saveContactsArchive(contacts)
resultContact = false
for c in contacts
if(c.id != nil)
resultContact = saveContactArchive(c)
else
resultContact = true
end
if(!resultContact)
ArchiveLogs.debug("Sauvegarde d'un contact sur l archive echoue, contact concerne "+c.inspect)
end
end
return resultContact
end
我正在尝试为所有这些模型创建一个父类,称为Archive。 这个课程定义了2个方法
class Archive
def saveOnArchive(element)
"Save on archive"
end
def saveArrayOnArchive(elements)
"Save an array on archive"
end
end
saveArrayOnArchive对所有模型都遵循相同的逻辑,例如saveContactsArchive;循环数组,为每个元素调用saveOnArchive,如果错误则写入日志。
我的问题;
1)更好的是创建模块化saveArrayOnArchive以及如何从父类调用children方法saveOnArchive?
2)我的模特会是什么样子?他们要重新划分每种方法吗?如果他们不向父方法添加任何内容,则调用super?
3)甚至可能,因为我的模型已经是来自activerecord的childreen class ArchContacts<的ActiveRecord :: Base的 - - 编辑 - - 为什么我的模特应该是ActiveRecord :: Base的孩子(我只是跟着另一个没有大脑的开发模型......) ---- ---- EDIT
3 in 1)如果有人理解我的话,如何实现这一目标......任何帮助都是有帮助的
答案 0 :(得分:1)
在你的情况下,它们似乎都具有相同的属性,因此你可以充分利用方法#becomes
,它创建一个具有当前类相同属性的不同类的新实例,例如< / p>
contact = Contact.first
archived_contact = contact.becomes ArchContact
archived_contact.save
这将创建存档的联系人,并为您节省复制每个属性的所有痛苦。
首先让我解释一下方法调用是如何工作的,每个实例都有一个方法调用冒泡的树,直到找到你要查找的方法,所以如果你调用saveOnArchive
,实例将查看它的类和检查是否存在具有该名称的方法,如果没有,则检查包含的模块,如果不是,则检查类的SuperClass,然后检查SuperClass的模块,一直到树,然后进入method_missing
打印错误的方法,说明找不到该方法。
我认为你不需要创建一个对象并且仅仅为2个方法提供它,你可以include
一个具有这些方法的模块,例如这里是归档模块。
module Archive
ef method_1
end
def method_2
end
end
然后将其包含在Contact类
中class Contact < ActiveRecord::Base
include Archive
end
现在您的Contact类有method_1
和method_2
,因为它们存在于查找树中,但由于您在不同的表中有不同的类和每个存档,您可以添加一些动态方法来处理这个,这是一个小例子
module Archive
def self.included(klass)
klass.instance_eval do
define_method "save_#{klass.name}_archive" do
self.becomes "#{klass.name}Archive".constantize
end
end
end
end
模块使用包含它的类并获取其名称来定义动态方法,在这种情况下,contact
模型将具有save_contact_archive
方法,该方法返回填充ContactArchive
的实例使用它的属性,您可以保存该对象。
但如果一个名为User
的类包含Archive
模块,则这些方法将被调用save_user_archive
并保存到名为UserArchive
的对象。
这个的简单用法是
contact = Contact.first
archived_contact = Contact.save_contact_archive
archived_contact.save
我希望我这么简单,如果你需要进一步的帮助,请问。
答案 1 :(得分:0)
您无法从多个类继承。但是,您可以将此功能放在模块中,例如
module Archivable
extend ActiveSupport::Concern
included do
class_attribute :archive_class
end
def save_in_archive
unless archive_exists?
archive_class.create(attributes.reject {|_, value| value.nil?}
end
end
#implement other methods such as archive_exists
end
然后你可以做类
class Contact
include Archivable
self.archive_class = ArchContacts
端
您可以执行以下操作:例如从模型名称推断存档类名称,或者将方法添加到包含模块并配置它的活动记录(如acts_as_list
),但基本方法是相同的。
我已经将您的方法更改为不逐个设置属性 - 如果没有,那么您将无法重用归档方法。如果您不希望归档所有属性,那么我将添加另一个class_attribute,它可以是白名单或属性名称的黑名单,您可以使用它来切片attributes
哈希。
您也可以考虑设置ArchContacts.record_timestamps = false
,否则rails会更新您可能不想要的updated_at
和created_at
列。