继承被误解了

时间:2015-05-05 07:16:54

标签: ruby-on-rails ruby inheritance

我正在尝试在我的应用中构建继承。

事实上,我很简单,我有几个模型,其中一些需要“归档”,它只是意味着我将数据从我的数据库公共原理图移动到归档原理图(相同的数据库)。

每个模型都有一个方法'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)如果有人理解我的话,如何实现这一目标......任何帮助都是有帮助的

2 个答案:

答案 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_1method_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_atcreated_at列。