active_merge 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.rdoc +16 -0
- data/{MIT-LICENSE → LICENSE} +1 -1
- data/README.rdoc +1 -1
- data/Rakefile +13 -1
- data/lib/active_merge/service.rb +57 -72
- data/lib/active_merge/simple_service.rb +36 -39
- data/lib/active_merge/version.rb +1 -2
- data/lib/active_merge.rb +9 -9
- data/spec/active_merge/service_spec.rb +205 -0
- data/spec/active_merge/simple_service_spec.rb +127 -0
- data/spec/active_merge_spec.rb +21 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/domain.rb +3 -0
- data/spec/dummy/app/models/lord.rb +4 -0
- data/spec/dummy/app/models/man.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +30 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/ru.yml +7 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20140416183029_create_lords.rb +6 -0
- data/spec/dummy/db/migrate/20140416183043_create_men.rb +8 -0
- data/spec/dummy/db/migrate/20140416183059_create_domains.rb +8 -0
- data/spec/dummy/db/schema.rb +31 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +38 -0
- data/spec/dummy/log/test.log +25184 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/spec_helper.rb +53 -0
- data/spec/support/errors.rb +17 -0
- metadata +125 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9908a773d23bf5b0b67850538549bf130646b257
|
4
|
+
data.tar.gz: e61c2879ca3ff6a256ac575651c69432b97c3c15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d189fc4e6e22e3806c1bcf7350130718c4e85170c6d9b51924a7b206cbbdbec9ecae588d339a36bec6fc2650b7a75d3883d51d718663159226b94e7cae6b4511
|
7
|
+
data.tar.gz: eccd6bbd86184af049cb31f3229b4c575ab9ba478c7b0b4a7e3ba97af443ec62467424761f25f8e5bd89ea9c3446dc000f3f73b789a787a1c16d13eb961fd1ac
|
data/CHANGELOG.rdoc
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
= Список изменений в версиях
|
2
|
+
|
3
|
+
== v.1.0.4
|
4
|
+
|
5
|
+
* The gem is allowed to use with rails 4.1
|
6
|
+
|
7
|
+
== v.1.0.2
|
8
|
+
|
9
|
+
* Documentation bug fixed. References to the <tt>#merge</tt> changed to the <tt>#merge_all</tt>
|
10
|
+
|
11
|
+
== v.1.0.1
|
12
|
+
|
13
|
+
* The <tt>Service#klass</tt> and <tt>Service#klasses</tt> methods removed
|
14
|
+
* The <tt>Service</tt> class includes <tt>ActiveModels::Validations</tt>
|
15
|
+
* The <tt>Service#valid?</tt> method added
|
16
|
+
* Service object errors collected in the <tt>Service#errors</tt>
|
data/{MIT-LICENSE → LICENSE}
RENAMED
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -20,10 +20,22 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
20
20
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
21
|
end
|
22
22
|
|
23
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
23
26
|
Bundler::GemHelper.install_tasks
|
24
27
|
|
25
28
|
require "bundler/gem_tasks"
|
26
29
|
require 'rspec/core/rake_task'
|
27
30
|
|
28
31
|
RSpec::Core::RakeTask.new(:spec)
|
29
|
-
task default
|
32
|
+
task :default do
|
33
|
+
sh "bundle exec rake db:migrate RAILS_ENV=test"
|
34
|
+
sh "mkdir spec/dummy/tmp" do |ok, res|
|
35
|
+
nunitSuccessFlag = false
|
36
|
+
end
|
37
|
+
sh "mkdir spec/dummy/tmp/cache" do |ok, res|
|
38
|
+
nunitSuccessFlag = false
|
39
|
+
end
|
40
|
+
sh "bundle exec rspec spec"
|
41
|
+
end
|
data/lib/active_merge/service.rb
CHANGED
@@ -1,24 +1,29 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module ActiveMerge
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
4
|
+
# Service Object responds for merging given ActiveRecord instances into the
|
5
|
+
# first one
|
6
6
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# они должны быть объектами одного класса.
|
7
|
+
# Object initializes either with ActiveRecord::Association or array of objects.
|
8
|
+
# If the argument is an array, then only those items taken into account, that:
|
10
9
|
#
|
11
|
-
#
|
12
|
-
# *
|
13
|
-
# *
|
14
|
-
# * После перепривязки все объекты, кроме первого, удаляются.
|
10
|
+
# * inherited from the <tt>ActiveRecord::Base</tt>
|
11
|
+
# * persisted
|
12
|
+
# * are objects of one class
|
15
13
|
#
|
16
|
-
#
|
17
|
-
# ранее относившиеся к объединяемым записям.
|
14
|
+
# == Merging algorithm
|
18
15
|
#
|
19
|
-
#
|
16
|
+
# * The item with minimal <tt>id</tt> selected from the service argument. It will remaine intact.
|
17
|
+
# * All objects, that the other items links to via "has_many" assotiation, are selected...
|
18
|
+
# * ... and are rebound to the first item
|
19
|
+
# * After rebinding any item from the service argument, except the first one, to be deleted.
|
20
20
|
#
|
21
|
-
#
|
21
|
+
# As a result it is only the first object from the argument remains intact,
|
22
|
+
# and all the instances that belonged to the other ones are now belongs to it.
|
23
|
+
#
|
24
|
+
# == Example:
|
25
|
+
#
|
26
|
+
# # Let any kingdom has many shires and men
|
22
27
|
# class Kingdom < ActiveRecord::Base
|
23
28
|
# has_many :shires
|
24
29
|
# has_many :men
|
@@ -32,102 +37,82 @@ module ActiveMerge
|
|
32
37
|
# belongs_to :kingdom
|
33
38
|
# end
|
34
39
|
#
|
35
|
-
# #
|
40
|
+
# # Britain has 10 shires and 100 thousands men lives there
|
36
41
|
# britain = Kingdom.create!
|
37
|
-
#
|
42
|
+
# 100000.times.each{ britain.men.create! }
|
38
43
|
# 10.times.each{ britain.shires.create! }
|
39
44
|
#
|
40
|
-
# #
|
45
|
+
# # Scotland has 5 shires and 30 thousands living men
|
41
46
|
# scotland = Kingdom.create!
|
42
|
-
#
|
43
|
-
# 5.times.each{
|
47
|
+
# 30000.times.each{ scotland.men.create! }
|
48
|
+
# 5.times.each{ scotland.shires.create! }
|
44
49
|
#
|
45
|
-
# #
|
50
|
+
# # Lets merge all the kingdoms:
|
46
51
|
# Service.new(Kingdom.all).submit!
|
47
52
|
#
|
48
|
-
# #
|
53
|
+
# # Now union Britain (because it is Britain that was created first)
|
54
|
+
# # has all those 15 shires and 130 thousand men
|
55
|
+
# # from both the old good Britain and the old good Scotland.
|
49
56
|
# britain.reload.men.count # => 130000
|
50
57
|
# britain.reload.shires.count # => 15
|
51
58
|
#
|
52
|
-
# #
|
59
|
+
# # And, alas, the Scotland Kingdom doesn't exists any more
|
53
60
|
# Kingdom.find_by(scotland.id) # => nil
|
54
61
|
#
|
55
|
-
# ==
|
62
|
+
# == Warning!
|
56
63
|
#
|
57
|
-
#
|
58
|
-
#
|
64
|
+
# The merge provided as a whole transaction. In case any error occures, all
|
65
|
+
# the changes rolled back.
|
59
66
|
#
|
60
|
-
#
|
61
|
-
# королевству (незыблемость суверенитета):
|
67
|
+
# Let (see the example above) the shire cannot be rebount to another kingdom:
|
62
68
|
#
|
63
69
|
# class Shire
|
64
70
|
# attr_readonly :kingdom_id
|
65
71
|
# end
|
66
72
|
#
|
67
|
-
#
|
73
|
+
# then merging won't be finished.
|
74
|
+
#
|
75
|
+
# Not only shires, but also the scots remain living in their Scotland,
|
76
|
+
# not in the United Kingdom!
|
68
77
|
#
|
69
|
-
class Service
|
78
|
+
class Service < ActivePatterns::BaseService
|
70
79
|
include ActiveModel::Validations
|
71
80
|
|
72
|
-
def initialize(list =
|
73
|
-
list =
|
81
|
+
def initialize(list = nil)
|
82
|
+
list = Items.new list
|
74
83
|
@item, @items = list.first, Array(list[1..-1])
|
75
84
|
end
|
76
85
|
|
77
86
|
attr_reader :item, :items, :klass, :klasses
|
78
87
|
validates :items, presence: true
|
79
88
|
|
80
|
-
#
|
81
|
-
#
|
82
|
-
# При этом:
|
83
|
-
# * все ссылки на записи из массива #items перепривязываются к #item
|
84
|
-
# * все записи #items удаляются
|
85
|
-
#
|
86
|
-
# При любой ошибке все сделанные изменения отменяются.
|
87
|
-
#
|
89
|
+
# Merges all the #items to the #item as a whole transaction
|
88
90
|
def provide
|
89
|
-
|
90
|
-
|
91
|
-
|
91
|
+
transaction do
|
92
|
+
items.each do |item|
|
93
|
+
service = SimpleService.new(self.item, item)
|
94
|
+
change(service) { service.provide }
|
95
|
+
end
|
92
96
|
end
|
93
97
|
end
|
94
98
|
|
95
99
|
private
|
96
100
|
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
list = select_by_class_from list
|
104
|
-
rescue
|
105
|
-
[]
|
101
|
+
# Returns only persisted items of the same ActiveRecord model
|
102
|
+
class Items < Array
|
103
|
+
def initialize(items)
|
104
|
+
items = Array(items).map{ |item| Item.new item }.compact
|
105
|
+
items = [] if items.map{ |item| item.class }.uniq.count > 1
|
106
|
+
super items.sort_by{ |item| item.id }
|
106
107
|
end
|
107
108
|
end
|
108
109
|
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
item.class.ancestors.include?
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
# Выбирает объекты того же класса, что и у первой записи списка
|
117
|
-
def select_by_class_from(list)
|
118
|
-
klass = list.first.class
|
119
|
-
list.each { |item| raise unless item.class == klass }
|
120
|
-
list.sort_by { |item| item.id }
|
121
|
-
end
|
122
|
-
|
123
|
-
# Объединяет две записи.
|
124
|
-
# Переносит ошибки в текущий объект.
|
125
|
-
def merge(first, second)
|
126
|
-
service = ActiveMerge::SimpleService.new(first, second)
|
127
|
-
begin
|
128
|
-
service.provide
|
129
|
-
rescue
|
130
|
-
service.errors.each{ |key, val| errors.add key, val } and raise
|
110
|
+
# Initializes a persisted item of an ActiveRecord model
|
111
|
+
class Item
|
112
|
+
def self.new(item)
|
113
|
+
return unless item.class.ancestors.include? ActiveRecord::Base
|
114
|
+
return unless item.persisted?
|
115
|
+
item
|
131
116
|
end
|
132
117
|
end
|
133
118
|
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module ActiveMerge
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
4
|
+
# Service Object responds for merging two ActiveRecord instances as a whole
|
5
|
+
# transaction.
|
6
6
|
#
|
7
|
-
#
|
8
|
-
#
|
7
|
+
# All objects linked to the second instance via "has_many" association
|
8
|
+
# are re-associated to the first one.
|
9
|
+
#
|
10
|
+
# Then the second instance removed.
|
11
|
+
# All errors collected in the #errors method.
|
9
12
|
#
|
10
|
-
|
11
|
-
# <tt>errors</tt>
|
12
|
-
#
|
13
|
-
class SimpleService
|
13
|
+
class SimpleService < ActivePatterns::BaseService
|
14
14
|
include ActiveModel::Validations
|
15
15
|
|
16
16
|
def initialize(first, second)
|
@@ -28,49 +28,46 @@ module ActiveMerge
|
|
28
28
|
validates :second, presence: true
|
29
29
|
|
30
30
|
def provide
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
destroy
|
31
|
+
transaction do
|
32
|
+
Links.new(second).each { |item, key| rebind(item, key) }
|
33
|
+
change(second) { second.destroy! }
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
38
37
|
private
|
39
38
|
|
40
|
-
#
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
# Initializes a hash, whose keys are instances linked to given one,
|
40
|
+
# and their values are names of methods for linking to another object.
|
41
|
+
class Links
|
42
|
+
class << self
|
43
|
+
|
44
|
+
def new(item)
|
45
|
+
@item = item
|
46
|
+
return hash
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns a hash whose keys are "has_many" associations' names
|
50
|
+
# and their values are corresponding foreign keys
|
51
|
+
def refs
|
52
|
+
@item.class.reflect_on_all_associations(:has_many).
|
53
|
+
inject({}){ |hash, item| hash.merge(item.name => item.foreign_key) }
|
54
|
+
end
|
46
55
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
56
|
+
def hash
|
57
|
+
@hash = {}
|
58
|
+
refs.each do |name, foreign_key|
|
59
|
+
@item.send(name).each{ |item| @hash[item] = "#{ foreign_key }=" }
|
60
|
+
end
|
61
|
+
@hash
|
62
|
+
end
|
53
63
|
end
|
54
|
-
return @refs
|
55
64
|
end
|
56
65
|
|
57
|
-
#
|
58
|
-
# Ошибки накапливаются в массиве <tt>errors</tt>
|
66
|
+
# Re-assigns given object to the #first
|
59
67
|
def rebind(item, key)
|
60
|
-
|
68
|
+
change item do
|
61
69
|
item.send key, first.id
|
62
70
|
item.save!
|
63
|
-
rescue
|
64
|
-
item.errors.each{ |key, val| errors.add key, val } and raise
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Удаляет объединяемый объект
|
69
|
-
def destroy
|
70
|
-
begin
|
71
|
-
second.destroy!
|
72
|
-
rescue
|
73
|
-
second.errors.each{ |key, val| errors.add key, val } and raise
|
74
71
|
end
|
75
72
|
end
|
76
73
|
end
|
data/lib/active_merge/version.rb
CHANGED
data/lib/active_merge.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
|
1
|
+
require "active_patterns"
|
2
2
|
|
3
|
-
#
|
3
|
+
# Declares service object for merging ActiveRecord instances.
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# After extending your active record model with the module,
|
6
|
+
# new <tt>::merge_all</tt> method is available.
|
7
7
|
#
|
8
8
|
module ActiveMerge
|
9
9
|
extend ActiveSupport::Autoload
|
@@ -11,18 +11,18 @@ module ActiveMerge
|
|
11
11
|
autoload :SimpleService
|
12
12
|
autoload :Service
|
13
13
|
|
14
|
-
#
|
14
|
+
# Merges instances from the association
|
15
15
|
#
|
16
16
|
# class Lord < ActiveRecord::Base
|
17
17
|
# extend ActiveMerge
|
18
18
|
# end
|
19
19
|
#
|
20
|
-
# Lord.all.merge_all
|
21
|
-
# Lord.where(id > 100) # =>
|
20
|
+
# Lord.all.merge_all # => merges all the class instances
|
21
|
+
# Lord.where("id > :id", id: 100) # => merges instances with id > 100
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# See details in <tt>ActiveMerge::Service#provide</tt> documentation.
|
24
24
|
#
|
25
25
|
def merge_all
|
26
|
-
ActiveMerge::Service.new(
|
26
|
+
ActiveMerge::Service.new(all).provide
|
27
27
|
end
|
28
28
|
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
module ActiveMerge
|
5
|
+
describe Service do
|
6
|
+
|
7
|
+
describe "#item" do
|
8
|
+
|
9
|
+
it "объявлен" do
|
10
|
+
Service.new.should respond_to :item
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#items" do
|
15
|
+
|
16
|
+
it "объявлен" do
|
17
|
+
Service.new.should respond_to :items
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "::new" do
|
22
|
+
|
23
|
+
let!(:items) { 3.times.map{ Man.create! }}
|
24
|
+
|
25
|
+
context "если передан запрос ActiveRelations" do
|
26
|
+
|
27
|
+
let!(:service) { Service.new Man.all }
|
28
|
+
|
29
|
+
it "присваивает переменной item первый объект (с минимальным id)" do
|
30
|
+
service.item.should eq Man.first
|
31
|
+
end
|
32
|
+
|
33
|
+
it "присваивает переменной items все объекты, кроме первого (с минимальным id)" do
|
34
|
+
service.items.should eq Man.all.order("id ASC").to_a[1..-1]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "если запрос возвращает только один элемент" do
|
39
|
+
|
40
|
+
let!(:service) { Service.new Man.where(id: Man.first.id) }
|
41
|
+
|
42
|
+
it "присваивает переменной item первый объект (с минимальным id)" do
|
43
|
+
service.item.should eq Man.first
|
44
|
+
end
|
45
|
+
|
46
|
+
it "присваивает переменной items пустой массив" do
|
47
|
+
service.items.should eq []
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "если запрос возвращает пустой массив" do
|
52
|
+
|
53
|
+
let!(:service) { Service.new Man.where(id: 0) }
|
54
|
+
|
55
|
+
it "присваивает nil переменной item" do
|
56
|
+
service.item.should be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "присваивает пустой массив переменной items" do
|
60
|
+
service.items.should eq []
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "если передан массив объектов ActiveRecord вместе с другими, non-Active record элементами" do
|
65
|
+
|
66
|
+
let!(:service) { Service.new (items + [Man.new, nil, 1]).shuffle }
|
67
|
+
|
68
|
+
it "присваивает переменной item первый объект (с минимальным id)" do
|
69
|
+
service.item.should eq Man.first
|
70
|
+
end
|
71
|
+
|
72
|
+
it "присваивает переменной items все сохраненные объекты, кроме первого (с минимальным id)" do
|
73
|
+
service.items.should eq Man.all.order("id ASC").to_a[1..-1]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "если переданный массив содержит только один сохраненный объект ActiveRecord" do
|
78
|
+
|
79
|
+
let!(:service) { Service.new [Man.first, 1, nil, Man.new] }
|
80
|
+
|
81
|
+
it "присваивает переменной item первый объект (с минимальным id)" do
|
82
|
+
service.item.should eq Man.first
|
83
|
+
end
|
84
|
+
|
85
|
+
it "присваивает переменной items пустой массив" do
|
86
|
+
service.items.should eq []
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "если массив не содержит сохраненных объектов ActiveRecord" do
|
91
|
+
|
92
|
+
let!(:service) { Service.new [1, nil, Man.new] }
|
93
|
+
|
94
|
+
it "присваивает nil переменной item" do
|
95
|
+
service.item.should be_nil
|
96
|
+
end
|
97
|
+
|
98
|
+
it "присваивает пустой массив переменной items" do
|
99
|
+
service.items.should eq []
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "если массив содержит сохраненные объекты ActiveRecord разных классов" do
|
104
|
+
|
105
|
+
let!(:service) { Service.new [Man.first, Domain.create!] }
|
106
|
+
|
107
|
+
it "присваивает nil переменной item" do
|
108
|
+
service.item.should be_nil
|
109
|
+
end
|
110
|
+
|
111
|
+
it "присваивает пустой массив переменной items" do
|
112
|
+
service.items.should eq []
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "если атрибут не передан" do
|
117
|
+
|
118
|
+
let!(:service) { Service.new }
|
119
|
+
|
120
|
+
it "присваивает nil переменной item" do
|
121
|
+
service.item.should be_nil
|
122
|
+
end
|
123
|
+
|
124
|
+
it "присваивает пустой массив переменной items" do
|
125
|
+
service.items.should eq []
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "#valid?" do
|
131
|
+
|
132
|
+
it "возвращает true если список записей для присоединения установлен" do
|
133
|
+
Service.new(2.times.map{ Lord.create! }).should be_valid
|
134
|
+
end
|
135
|
+
|
136
|
+
it "возвращает false если список записей для присоединения пуст" do
|
137
|
+
service = Service.new [Lord.create!]
|
138
|
+
service.should_not be_valid
|
139
|
+
service.errors.should_not be_blank
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "#provide" do
|
144
|
+
|
145
|
+
let!(:lords) { 2.times.map{ Lord.create! }}
|
146
|
+
let!(:domains) { lords.map{ |lord| lord.domains.create! }}
|
147
|
+
let!(:men) { lords.map{ |lord| lord.men.create! }}
|
148
|
+
let!(:service) { Service.new lords }
|
149
|
+
|
150
|
+
context "если перепривязка разрешена" do
|
151
|
+
|
152
|
+
it "не вызывает исключений" do
|
153
|
+
expect{ service.provide }.not_to raise_error
|
154
|
+
end
|
155
|
+
|
156
|
+
it "объединяет записи" do
|
157
|
+
begin; service.provide; rescue; end
|
158
|
+
Lord.count.should eq 1
|
159
|
+
Lord.first.domains.count.should eq 2
|
160
|
+
Lord.first.men.count.should eq 2
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "если перепривязка не может быть выполнена" do
|
165
|
+
|
166
|
+
before do
|
167
|
+
service.items.last.stub(:destroy!).and_raise
|
168
|
+
service.items.last.stub(:errors).and_return({ base: "Удаление запрещено." })
|
169
|
+
end
|
170
|
+
|
171
|
+
it "вызывает исключение" do
|
172
|
+
expect{ service.provide }.to raise_error
|
173
|
+
end
|
174
|
+
|
175
|
+
it "не объединяет записи" do
|
176
|
+
begin; service.provide; rescue; end
|
177
|
+
Lord.count.should eq 2
|
178
|
+
Lord.all.each do |lord|
|
179
|
+
lord.domains.count.should eq 1
|
180
|
+
lord.men.count.should eq 1
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
it "добавляет ошибки в массив" do
|
185
|
+
begin; service.provide; rescue; end
|
186
|
+
service.errors.should_not be_blank
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context "если атрибут #items пуст" do
|
191
|
+
|
192
|
+
before { service.stub(:items).and_return [] }
|
193
|
+
|
194
|
+
it "вызывает исключение" do
|
195
|
+
expect{ service.provide }.to raise_error
|
196
|
+
end
|
197
|
+
|
198
|
+
it "добавляет ошибки в массив" do
|
199
|
+
begin; service.provide; rescue; end
|
200
|
+
service.errors.should_not be_blank
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|