Class: ActiveMerge::Service

Inherits:
ActivePatterns::BaseService
  • Object
show all
Includes:
ActiveModel::Validations
Defined in:
lib/active_merge/service.rb

Overview

Service Object responds for merging given ActiveRecord instances into the first one

Object initializes either with ActiveRecord::Association or array of objects. If the argument is an array, then only those items taken into account, that:

  • inherited from the ActiveRecord::Base

  • persisted

  • are objects of one class

Merging algorithm

  • The item with minimal id selected from the service argument. It will remaine intact.

  • All objects, that the other items links to via “has_many” assotiation, are selected…

  • … and are rebound to the first item

  • After rebinding any item from the service argument, except the first one, to be deleted.

As a result it is only the first object from the argument remains intact, and all the instances that belonged to the other ones are now belongs to it.

Example:

# Let any kingdom has many shires and men
class Kingdom < ActiveRecord::Base
  has_many :shires
  has_many :men
end

class Shire < ActiveRecord::Base
  belongs_to :kingdom
end

class Man < ActiveRecord::Base
  belongs_to :kingdom
end

# Britain has 10 shires and 100 thousands men lives there
britain  = Kingdom.create!
100000.times.each{ britain.men.create! }
10.times.each{ britain.shires.create! }

# Scotland has 5 shires and 30 thousands living men
scotland = Kingdom.create!
30000.times.each{ scotland.men.create! }
5.times.each{ scotland.shires.create! }

# Lets merge all the kingdoms:
Service.new(Kingdom.all).provide

# Now union Britain (because it is Britain that was created first) 
# has all those 15 shires and 130 thousand men
# from both the old good Britain and the old good Scotland.
britain.reload.men.count # => 130000
britain.reload.shires.count # => 15

# And, alas, the Scotland Kingdom doesn't exists any more
Kingdom.find_by(scotland.id)  # => nil

Warning!

The merge provided as a whole transaction. In case of any error, all changes roll back.

Let (see the example above) the shire cannot be rebount to another kingdom:

class Shire
  attr_readonly :kingdom_id
end

In this case the merge won’t be finished. Not only shires, but also scots remain living in their old good Scotland!

Skipping activerecord validations

You can use the validate: false option.

With this option set any activerecord validation and callback skipped.

Service.new(Kingdom.all).provide validate: false

Defined Under Namespace

Classes: Item, Items

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(list = nil) ⇒ Service

Returns a new instance of Service.



89
90
91
92
# File 'lib/active_merge/service.rb', line 89

def initialize(list = nil)
  list = Items.new list
  @item, @items = list.first, Array(list[1..-1])
end

Instance Attribute Details

#itemObject (readonly)

Returns the value of attribute item.



94
95
96
# File 'lib/active_merge/service.rb', line 94

def item
  @item
end

#itemsObject (readonly)

Returns the value of attribute items.



94
95
96
# File 'lib/active_merge/service.rb', line 94

def items
  @items
end

#klassObject (readonly)

Returns the value of attribute klass.



94
95
96
# File 'lib/active_merge/service.rb', line 94

def klass
  @klass
end

#klassesObject (readonly)

Returns the value of attribute klasses.



94
95
96
# File 'lib/active_merge/service.rb', line 94

def klasses
  @klasses
end

Instance Method Details

#provide(options = {}) ⇒ Object

Merges all the #items to the #item as a whole transaction



98
99
100
101
102
103
104
105
# File 'lib/active_merge/service.rb', line 98

def provide(options = {})
  transaction do
    items.each do |item|
      service = SimpleService.new(self.item, item)
      change(service) { service.provide(options) }
    end
  end
end