Sha256: 30e4b09c234c588fd30d6393d2b09c95d39ddabc26f28bbe7ca274f334d60698

Contents?: true

Size: 1.92 KB

Versions: 1

Compression:

Stored size: 1.92 KB

Contents

# encoding: utf-8
module ActiveMerge

  # Service Object responds for merging two ActiveRecord instances as a whole
  # transaction.
  #
  # All objects linked to the second instance via "has_many" association
  # are re-associated to the first one.
  # 
  # Then the second instance removed.
  # All errors collected in the #errors method.
  #
  class SimpleService < ActivePatterns::BaseService
    include ActiveModel::Validations

    def initialize(first, second)

      if first.class.ancestors.include?(ActiveRecord::Base) && first.persisted?
        @first = first
      end

      if @first && (second.class == @first.class) && second.persisted?
        @second = second
      end
    end
    attr_reader :first, :second

    validates :second, presence: true

    def provide
      transaction do
        Links.new(second).each { |item, key| rebind(item, key) }
        change(second) { second.destroy! }
      end
    end

    private

      # Initializes a hash, whose keys are instances linked to given one,
      # and their values are names of methods for linking to another object.
      class Links
        class << self

          def new(item)
            @item = item
            return hash
          end

          # Returns a hash whose keys are "has_many" associations' names
          # and their values are corresponding foreign keys
          def refs
            @item.class.reflect_on_all_associations(:has_many).
              inject({}){ |hash, item| hash.merge(item.name => item.foreign_key) }
          end

          def hash
            @hash = {}
            refs.each do |name, foreign_key|
              @item.send(name).each{ |item| @hash[item] = "#{ foreign_key }=" }
            end
            @hash
          end
        end
      end

      # Re-assigns given object to the #first
      def rebind(item, key)
        change item do
          item.send key, first.id
          item.save!
        end
      end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
active_merge-1.0.5 lib/active_merge/simple_service.rb