Переназначение экземпляра ActiveRecord и соответствующих внешних ключей - PullRequest
4 голосов
/ 22 сентября 2011

В Rails / ActiveReocrd есть способ заменить один экземпляр другим, чтобы все отношения / внешние ключи были разрешены.

Я мог бы представить что-то вроде этого:

//setup
customer1 = Customer.find(1)
customer2 = Customer.find(2)

//this would be cool
customer1.replace_with(customer2)

предположим, что customer1 был плохо настроен, а кто-то ушел и создал customer2, не зная о customer1, было бы неплохо иметь возможность быстро настроить все на customer 2

Таким образом, также необходимо обновить все внешние ключи

Пользователь принадлежит_: клиент Сайт принадлежит: клиенту

тогда любые пользователи / веб-сайты с внешним ключом customer_id = 1 автоматически получат значение 2 с помощью этого метода replace_with

Существует ли такая вещь?

[Я могу представить себе взлом с участием Customer.reflect_on_all_associations (: has_many) и т. Д.]

Ура, J

1 Ответ

1 голос
/ 22 сентября 2011

Примерно так может работать, хотя может быть более правильный путь:

Обновлено : исправлено несколько ошибок в примере ассоциаций.

class MyModel < ActiveRecord::Base

  ...

  # if needed, force logout / expire session in controller beforehand.
  def replace_with (another_record)
    # handles attributes and belongs_to associations
    attribute_hash = another_record.attributes
    attribute_hash.delete('id')
    self.update_attributes!(attribute_hash)

    ### Begin association example, not complete.

    # generic way of finding model constants
    find_model_proc = Proc.new{ |x| x.to_s.singularize.camelize.constantize }
    model_constant = find_model_proc.call(self.class.name)

    # handle :has_one, :has_many associations
    have_ones = model_constant.reflect_on_all_associations(:has_one).find_all{|i| !i.options.include?(:through)}
    have_manys = model_constant.reflect_on_all_associations(:has_many).find_all{|i| !i.options.include?(:through)}

    update_assoc_proc = Proc.new do |assoc, associated_record, id|
      primary_key = assoc.primary_key_name.to_sym
      attribs = associated_record.attributes
      attribs[primary_key] = self.id
      associated_record.update_attributes!(attribs)
    end

    have_ones.each do |assoc|
      associated_record = self.send(assoc.name)
      unless associated_record.nil?
        update_assoc_proc.call(assoc, associated_record, self.id)
      end
    end

    have_manys.each do |assoc|
      associated_records = self.send(assoc.name)
      associated_records.each do |associated_record|
        update_assoc_proc.call(assoc, associated_record, self.id)
      end
    end

    ### End association example, not complete.

    # and if desired..
    # do not call :destroy if you have any associations set with :dependents => :destroy
    another_record.destroy
  end

  ...

end

Я включил пример того, как вы можете справиться с некоторыми ассоциациями, но в целом это может быть сложно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...