2015-05-05 3 views
1

Я пытаюсь построить наследование в своем приложении.Inheritance misunderstood

На самом деле все просто, у меня есть несколько моделей, и некоторые из них должны быть «архивами», это просто означает, что я собираюсь перенести данные из моей открытой схемы базы данных в схему архива (та же база данных).

Каждый модели имеют save'itself'OnArchive Способы»на примере:

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 

и некоторые из моделей имеют methodes save'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. Этот класс woud определяют 2 метода

class Archive 
    def saveOnArchive(element) 
    "Save on archive" 
    end 
    def saveArrayOnArchive(elements) 
    "Save an array on archive" 
    end 
end 

saveArrayOnArchive следовать той же логике, для всех моделей, как для saveContactsArchive; loop on array, для каждого вызова элемента saveOnArchive, записывать журналы, если ошибка.

Мои вопросы;

1) что лучше создать модульный saveArrayOnArchive и как вызвать метод children saveOnArchive из родительского класса?

2) Какие модели будут выглядеть? переделать ли они все методы? вызов супер, если они ничего не добавляют к родительскому методу?

3) является то, что даже возможно, так как мои модели уже childreen от ActiveRecord класса ArchContacts < ActiveRecord :: Base ---- EDIT ---- Почему Шоуда мои модели быть детьми ActiveRecord :: Base (I просто следовал другой модели DEV без мозга ....) ---- EDIT ----

3 в 1) Как добиться этого, если кто-то меня понял ... любая помощь apricieted

ответ

1

в в вашем случае все они имеют одинаковые атрибуты, поэтому вы можете хорошо использовать метод #becomes, который создает новый i nstance другого класса с теми же атрибутами текущего класса, например

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 

Затем включите его в Контактном классе

class Contact < ActiveRecord::Base 
    include Archive 
end 

Теперь ваш Контакт класс имеет method_1 и method_2, потому что они существуют в смотреть вверх дерево, но так как у вас есть разные классы и каждый архив в Differnet таблиц , вы можете добавить небольшой динамический метод для этого, вот небольшой пример

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 

В модуле используется класс t hat включил его и получил свое имя для определения динамических методов, в этом случае модель contact будет иметь метод save_contact_archive, который возвращает экземпляр ContactArchive, заполненный его атрибутами, и вы можете сохранить этот объект.

Но если класс называется User Inculded в Archive модуль, методы будут называться save_user_archive, и это экономит на объект под названием UserArchive.

Простое использование этого было бы

contact = Contact.first 
archived_contact = Contact.save_contact_archive 
archived_contact.save 

Я надеюсь, что я сделал это просто, если вам нужна дополнительная помощь, пожалуйста, спросите.

+0

Это выглядит потрясающе !!! идеальное решение для моих нужд, мне понадобится несколько раз, чтобы понять все, но я за него :)! Спасибо !! –

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, иначе рельсы будут обновлять столбцы updated_at и created_at, которые вы, по-видимому, не хотите.

+0

другие отличные решения, попробуем их обоих, спасибо! –