amoeba 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/jruby.yml +27 -0
- data/.github/workflows/ruby_25.yml +30 -0
- data/.github/workflows/ruby_26.yml +30 -0
- data/.github/workflows/ruby_27.yml +30 -0
- data/.github/workflows/ruby_30.yml +34 -0
- data/.github/workflows/ruby_31.yml +34 -0
- data/.github/workflows/ruby_32.yml +34 -0
- data/.github/workflows/ruby_head.yml +34 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +11 -7
- data/.rubocop_todo.yml +120 -0
- data/Appraisals +48 -9
- data/CHANGELOG.md +14 -0
- data/Gemfile +5 -2
- data/LICENSE.md +11 -0
- data/README.md +3 -17
- data/Rakefile +2 -0
- data/amoeba.gemspec +20 -17
- data/gemfiles/activerecord_5.2.gemfile +19 -0
- data/gemfiles/activerecord_6.0.gemfile +19 -0
- data/gemfiles/activerecord_6.1.gemfile +19 -0
- data/gemfiles/activerecord_7.0.gemfile +19 -0
- data/gemfiles/activerecord_head.gemfile +10 -12
- data/gemfiles/jruby_activerecord_7.0.gemfile +20 -0
- data/gemfiles/jruby_activerecord_head.gemfile +26 -0
- data/lib/amoeba/class_methods.rb +2 -0
- data/lib/amoeba/cloner.rb +11 -4
- data/lib/amoeba/config.rb +25 -51
- data/lib/amoeba/instance_methods.rb +3 -0
- data/lib/amoeba/macros/base.rb +4 -1
- data/lib/amoeba/macros/has_and_belongs_to_many.rb +2 -0
- data/lib/amoeba/macros/has_many.rb +2 -0
- data/lib/amoeba/macros/has_one.rb +4 -0
- data/lib/amoeba/macros.rb +2 -0
- data/lib/amoeba/version.rb +3 -1
- data/lib/amoeba.rb +6 -2
- data/spec/lib/amoeba_spec.rb +76 -34
- data/spec/spec_helper.rb +13 -5
- data/spec/support/data.rb +22 -15
- data/spec/support/models.rb +39 -38
- metadata +66 -30
- data/.travis.yml +0 -20
- data/gemfiles/activerecord_4.0.gemfile +0 -17
- data/gemfiles/activerecord_4.1.gemfile +0 -17
- data/gemfiles/activerecord_4.2.gemfile +0 -17
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gem 'activerecord', '~> 5.2.0'
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem 'rake'
|
9
|
+
gem 'simplecov', '~> 0.21.2'
|
10
|
+
gem 'simplecov-lcov', '~> 0.8.0'
|
11
|
+
gem 'sqlite3', '~> 1.3.0'
|
12
|
+
end
|
13
|
+
|
14
|
+
group :local_development do
|
15
|
+
gem 'appraisal'
|
16
|
+
gem 'pry'
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec path: '../'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gem 'activerecord', '~> 6.0.0'
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem 'rake'
|
9
|
+
gem 'simplecov', '~> 0.21.2'
|
10
|
+
gem 'simplecov-lcov', '~> 0.8.0'
|
11
|
+
gem 'sqlite3', '~> 1.6.0'
|
12
|
+
end
|
13
|
+
|
14
|
+
group :local_development do
|
15
|
+
gem 'appraisal'
|
16
|
+
gem 'pry'
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec path: '../'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gem 'activerecord', '~> 6.1.0'
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem 'rake'
|
9
|
+
gem 'simplecov', '~> 0.21.2'
|
10
|
+
gem 'simplecov-lcov', '~> 0.8.0'
|
11
|
+
gem 'sqlite3', '~> 1.6.0'
|
12
|
+
end
|
13
|
+
|
14
|
+
group :local_development do
|
15
|
+
gem 'appraisal'
|
16
|
+
gem 'pry'
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec path: '../'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gem 'activerecord', '~> 7.0.0'
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem 'rake'
|
9
|
+
gem 'simplecov', '~> 0.21.2'
|
10
|
+
gem 'simplecov-lcov', '~> 0.8.0'
|
11
|
+
gem 'sqlite3', '~> 1.6.0'
|
12
|
+
end
|
13
|
+
|
14
|
+
group :local_development do
|
15
|
+
gem 'appraisal'
|
16
|
+
gem 'pry'
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec path: '../'
|
@@ -1,23 +1,21 @@
|
|
1
1
|
# This file was generated by Appraisal
|
2
2
|
|
3
|
-
source
|
3
|
+
source 'https://rubygems.org'
|
4
4
|
|
5
|
-
git
|
6
|
-
gem
|
7
|
-
end
|
8
|
-
|
9
|
-
git "git://github.com/rails/rails.git" do
|
10
|
-
gem "activerecord"
|
5
|
+
git 'https://github.com/rails/rails.git', branch: 'main' do
|
6
|
+
gem 'activerecord'
|
11
7
|
end
|
12
8
|
|
13
9
|
group :development, :test do
|
14
|
-
gem
|
15
|
-
gem
|
10
|
+
gem 'rake'
|
11
|
+
gem 'simplecov', '~> 0.21.2'
|
12
|
+
gem 'simplecov-lcov', '~> 0.8.0'
|
13
|
+
gem 'sqlite3', '~> 1.6.0'
|
16
14
|
end
|
17
15
|
|
18
16
|
group :local_development do
|
19
|
-
gem
|
20
|
-
gem
|
17
|
+
gem 'appraisal'
|
18
|
+
gem 'pry'
|
21
19
|
end
|
22
20
|
|
23
|
-
gemspec :
|
21
|
+
gemspec path: '../'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gem 'activerecord', '~> 7.0.0'
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem 'activerecord-jdbc-adapter', '~> 70.1'
|
9
|
+
gem 'activerecord-jdbcsqlite3-adapter', '~> 70.1'
|
10
|
+
gem 'rake'
|
11
|
+
gem 'simplecov', '~> 0.21.2'
|
12
|
+
gem 'simplecov-lcov', '~> 0.8.0'
|
13
|
+
end
|
14
|
+
|
15
|
+
group :local_development do
|
16
|
+
gem 'appraisal'
|
17
|
+
gem 'pry'
|
18
|
+
end
|
19
|
+
|
20
|
+
gemspec path: '../'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
git 'https://github.com/rails/rails.git', branch: 'main' do
|
6
|
+
gem 'activerecord'
|
7
|
+
end
|
8
|
+
|
9
|
+
group :development, :test do
|
10
|
+
git 'https://github.com/jruby/activerecord-jdbc-adapter' do
|
11
|
+
gem 'activerecord-jdbc-adapter'
|
12
|
+
gem 'activerecord-jdbcsqlite3-adapter',
|
13
|
+
glob: 'activerecord-jdbcsqlite3-adapter/activerecord-jdbcsqlite3-adapter.gemspec'
|
14
|
+
end
|
15
|
+
|
16
|
+
gem 'rake'
|
17
|
+
gem 'simplecov', '~> 0.21.2'
|
18
|
+
gem 'simplecov-lcov', '~> 0.8.0'
|
19
|
+
end
|
20
|
+
|
21
|
+
group :local_development do
|
22
|
+
gem 'appraisal'
|
23
|
+
gem 'pry'
|
24
|
+
end
|
25
|
+
|
26
|
+
gemspec path: '../'
|
data/lib/amoeba/class_methods.rb
CHANGED
data/lib/amoeba/cloner.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'forwardable'
|
2
4
|
|
3
5
|
module Amoeba
|
@@ -29,7 +31,7 @@ module Amoeba
|
|
29
31
|
private
|
30
32
|
|
31
33
|
def parenting_style
|
32
|
-
amoeba.upbringing
|
34
|
+
amoeba.upbringing || _parent_amoeba.parenting
|
33
35
|
end
|
34
36
|
|
35
37
|
def inherit_strict_parent_settings
|
@@ -47,8 +49,9 @@ module Amoeba
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def inherit_parent_settings
|
50
|
-
return
|
51
|
-
return unless %w
|
52
|
+
return unless _parent_amoeba.inherit
|
53
|
+
return unless %w[strict relaxed submissive].include?(parenting_style.to_s)
|
54
|
+
|
52
55
|
__send__("inherit_#{parenting_style}_parent_settings".to_sym)
|
53
56
|
end
|
54
57
|
|
@@ -67,12 +70,14 @@ module Amoeba
|
|
67
70
|
# and old children on the copy
|
68
71
|
return unless association.macro == :has_many ||
|
69
72
|
association.is_a?(::ActiveRecord::Reflection::ThroughReflection)
|
73
|
+
|
70
74
|
amoeba.exclude_association(association.options[:through])
|
71
75
|
end
|
72
76
|
|
73
77
|
def follow_only_includes
|
74
78
|
amoeba.includes.each do |include, options|
|
75
79
|
next if options[:if] && !@old_object.send(options[:if])
|
80
|
+
|
76
81
|
follow_association(include, @object_klass.reflect_on_association(include))
|
77
82
|
end
|
78
83
|
end
|
@@ -81,6 +86,7 @@ module Amoeba
|
|
81
86
|
@object_klass.reflections.each do |name, association|
|
82
87
|
exclude = amoeba.excludes[name.to_sym]
|
83
88
|
next if exclude && (exclude.blank? || @old_object.send(exclude[:if]))
|
89
|
+
|
84
90
|
follow_association(name, association)
|
85
91
|
end
|
86
92
|
end
|
@@ -108,8 +114,9 @@ module Amoeba
|
|
108
114
|
|
109
115
|
def follow_association(relation_name, association)
|
110
116
|
return unless amoeba.known_macros.include?(association.macro.to_sym)
|
117
|
+
|
111
118
|
follow_klass = ::Amoeba::Macros.list[association.macro.to_sym]
|
112
|
-
follow_klass
|
119
|
+
follow_klass&.new(self)&.follow(relation_name, association)
|
113
120
|
end
|
114
121
|
|
115
122
|
def process_overrides
|
data/lib/amoeba/config.rb
CHANGED
@@ -1,43 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Amoeba
|
2
4
|
class Config
|
3
5
|
DEFAULTS = {
|
4
|
-
enabled:
|
5
|
-
inherit:
|
6
|
-
do_preproc:
|
7
|
-
parenting:
|
8
|
-
raised:
|
9
|
-
dup_method:
|
10
|
-
remap_method:
|
11
|
-
includes:
|
12
|
-
excludes:
|
13
|
-
clones:
|
6
|
+
enabled: false,
|
7
|
+
inherit: false,
|
8
|
+
do_preproc: false,
|
9
|
+
parenting: false,
|
10
|
+
raised: false,
|
11
|
+
dup_method: :dup,
|
12
|
+
remap_method: nil,
|
13
|
+
includes: {},
|
14
|
+
excludes: {},
|
15
|
+
clones: [],
|
14
16
|
customizations: [],
|
15
|
-
overrides:
|
16
|
-
null_fields:
|
17
|
-
coercions:
|
18
|
-
prefixes:
|
19
|
-
suffixes:
|
20
|
-
regexes:
|
21
|
-
known_macros:
|
22
|
-
}
|
23
|
-
|
24
|
-
# ActiveRecord 3.x have different implementation of deep_dup
|
25
|
-
if ::ActiveRecord::VERSION::MAJOR == 3
|
26
|
-
DEFAULTS.instance_eval do
|
27
|
-
def deep_dup
|
28
|
-
each_with_object(dup) do |(key, value), hash|
|
29
|
-
hash[key.deep_dup] = value.deep_dup
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
Object.class_eval do
|
34
|
-
def deep_dup
|
35
|
-
duplicable? ? dup : self
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
DEFAULTS.freeze
|
17
|
+
overrides: [],
|
18
|
+
null_fields: [],
|
19
|
+
coercions: {},
|
20
|
+
prefixes: {},
|
21
|
+
suffixes: {},
|
22
|
+
regexes: {},
|
23
|
+
known_macros: %i[has_one has_many has_and_belongs_to_many]
|
24
|
+
}.freeze
|
41
25
|
|
42
26
|
DEFAULTS.each do |key, value|
|
43
27
|
value.freeze if value.is_a?(Array) || value.is_a?(Hash)
|
@@ -53,7 +37,7 @@ module Amoeba
|
|
53
37
|
@config = self.class::DEFAULTS.deep_dup
|
54
38
|
end
|
55
39
|
|
56
|
-
|
40
|
+
alias upbringing raised
|
57
41
|
|
58
42
|
def enable
|
59
43
|
@config[:enabled] = true
|
@@ -110,35 +94,25 @@ module Amoeba
|
|
110
94
|
def include_association(value = nil, options = {})
|
111
95
|
enable
|
112
96
|
@config[:excludes] = {}
|
113
|
-
|
97
|
+
value = value.is_a?(Array) ? value.map! { |v| [v, options] }.to_h : { value => options }
|
98
|
+
push_value_to_hash(value, :includes)
|
114
99
|
end
|
115
100
|
|
116
101
|
def include_associations(*values)
|
117
102
|
values.flatten.each { |v| include_association(v) }
|
118
103
|
end
|
119
104
|
|
120
|
-
# TODO: remove this method in v3.0.0
|
121
|
-
def include_field(value = nil)
|
122
|
-
warn 'include_field is deprecated and will be removed in version 3.0.0; please use include_association instead'
|
123
|
-
include_association(value)
|
124
|
-
end
|
125
|
-
|
126
105
|
def exclude_association(value = nil, options = {})
|
127
106
|
enable
|
128
107
|
@config[:includes] = {}
|
129
|
-
|
108
|
+
value = value.is_a?(Array) ? value.map! { |v| [v, options] }.to_h : { value => options }
|
109
|
+
push_value_to_hash(value, :excludes)
|
130
110
|
end
|
131
111
|
|
132
112
|
def exclude_associations(*values)
|
133
113
|
values.flatten.each { |v| exclude_association(v) }
|
134
114
|
end
|
135
115
|
|
136
|
-
# TODO: remove this method in v3.0.0
|
137
|
-
def exclude_field(value = nil)
|
138
|
-
warn 'exclude_field is deprecated and will be removed in version 3.0.0; please use exclude_association instead'
|
139
|
-
exclude_association(value)
|
140
|
-
end
|
141
|
-
|
142
116
|
def clone(value = nil)
|
143
117
|
enable
|
144
118
|
push_value_to_array(value, :clones)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Amoeba
|
2
4
|
module InstanceMethods
|
3
5
|
def _parent_amoeba
|
@@ -10,6 +12,7 @@ module Amoeba
|
|
10
12
|
|
11
13
|
def _first_superclass_with_amoeba
|
12
14
|
return @_first_superclass_with_amoeba unless @_first_superclass_with_amoeba.nil?
|
15
|
+
|
13
16
|
klass = self.class
|
14
17
|
while klass.superclass < ::ActiveRecord::Base
|
15
18
|
klass = klass.superclass
|
data/lib/amoeba/macros/base.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Amoeba
|
2
4
|
module Macros
|
3
5
|
class Base
|
@@ -8,7 +10,7 @@ module Amoeba
|
|
8
10
|
end
|
9
11
|
|
10
12
|
def follow(_relation_name, _association)
|
11
|
-
|
13
|
+
raise "#{self.class.name} doesn't implement `follow`!"
|
12
14
|
end
|
13
15
|
|
14
16
|
class << self
|
@@ -19,6 +21,7 @@ module Amoeba
|
|
19
21
|
|
20
22
|
def remapped_relation_name(name)
|
21
23
|
return name unless @cloner.amoeba.remap_method
|
24
|
+
|
22
25
|
@old_object.__send__(@cloner.amoeba.remap_method, name.to_sym) || name
|
23
26
|
end
|
24
27
|
end
|
@@ -1,10 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Amoeba
|
2
4
|
module Macros
|
3
5
|
class HasOne < ::Amoeba::Macros::Base
|
4
6
|
def follow(relation_name, association)
|
5
7
|
return if association.is_a?(::ActiveRecord::Reflection::ThroughReflection)
|
8
|
+
|
6
9
|
old_obj = @old_object.__send__(relation_name)
|
7
10
|
return unless old_obj
|
11
|
+
|
8
12
|
copy_of_obj = old_obj.amoeba_dup(@options)
|
9
13
|
copy_of_obj[:"#{association.foreign_key}"] = nil
|
10
14
|
relation_name = remapped_relation_name(relation_name)
|
data/lib/amoeba/macros.rb
CHANGED
data/lib/amoeba/version.rb
CHANGED
data/lib/amoeba.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record'
|
2
4
|
require 'active_support/all'
|
3
5
|
require 'amoeba/version'
|
@@ -14,5 +16,7 @@ require 'amoeba/instance_methods'
|
|
14
16
|
module Amoeba
|
15
17
|
end
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
ActiveSupport.on_load :active_record do
|
20
|
+
extend Amoeba::ClassMethods
|
21
|
+
include Amoeba::InstanceMethods
|
22
|
+
end
|
data/spec/lib/amoeba_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe 'amoeba' do
|
4
4
|
context 'dup' do
|
5
|
-
before
|
5
|
+
before do
|
6
6
|
require ::File.dirname(__FILE__) + '/../support/data.rb'
|
7
7
|
end
|
8
8
|
|
@@ -73,12 +73,17 @@ describe 'amoeba' do
|
|
73
73
|
expect(new_post.supercats.map(&:ramblings)).to include('Copy of zomg')
|
74
74
|
expect(new_post.supercats.map(&:other_ramblings).uniq.length).to eq(1)
|
75
75
|
expect(new_post.supercats.map(&:other_ramblings).uniq).to include('La la la')
|
76
|
-
expect(new_post.contents).to eq("Here's a copy: #{old_post.contents.gsub(/dog/,
|
76
|
+
expect(new_post.contents).to eq("Here's a copy: #{old_post.contents.gsub(/dog/,
|
77
|
+
'cat')} (copied version)")
|
77
78
|
expect(new_post.comments.length).to eq(5)
|
78
|
-
expect(new_post.comments.select
|
79
|
+
expect(new_post.comments.select do |c|
|
80
|
+
c.nerf == 'ratatat' && c.contents.nil?
|
81
|
+
end.length).to eq(1)
|
79
82
|
expect(new_post.comments.select { |c| c.nerf == 'ratatat' }.length).to eq(2)
|
80
83
|
expect(new_post.comments.select { |c| c.nerf == 'bonk' }.length).to eq(1)
|
81
|
-
expect(new_post.comments.select
|
84
|
+
expect(new_post.comments.select do |c|
|
85
|
+
c.nerf == 'bonkers' && c.contents.nil?
|
86
|
+
end.length).to eq(1)
|
82
87
|
|
83
88
|
new_post.widgets.map(&:id).each do |id|
|
84
89
|
expect(old_post.widgets.map(&:id)).not_to include(id)
|
@@ -96,7 +101,9 @@ describe 'amoeba' do
|
|
96
101
|
expect(new_author.errors.messages).to be_empty
|
97
102
|
expect(new_author.posts.first.custom_things.length).to eq(3)
|
98
103
|
expect(new_author.posts.first.custom_things.select { |ct| ct.value == [] }.length).to eq(1)
|
99
|
-
expect(new_author.posts.first.custom_things.select
|
104
|
+
expect(new_author.posts.first.custom_things.select do |ct|
|
105
|
+
ct.value == [1, 2]
|
106
|
+
end.length).to eq(1)
|
100
107
|
expect(new_author.posts.first.custom_things.select { |ct| ct.value == [78] }.length).to eq(1)
|
101
108
|
# }}}
|
102
109
|
# Products {{{
|
@@ -176,60 +183,90 @@ describe 'amoeba' do
|
|
176
183
|
end
|
177
184
|
end
|
178
185
|
|
179
|
-
context '
|
186
|
+
context 'Using a if condition' do
|
187
|
+
subject { post.amoeba_dup.save! }
|
188
|
+
|
180
189
|
before(:all) do
|
181
190
|
require ::File.dirname(__FILE__) + '/../support/data.rb'
|
182
191
|
end
|
192
|
+
|
183
193
|
before { ::Post.fresh_amoeba }
|
184
194
|
|
185
|
-
subject { post.amoeba_dup.save! }
|
186
195
|
let(:post) { Post.first }
|
187
196
|
|
188
|
-
it 'includes
|
197
|
+
it 'includes an association with truthy condition' do
|
189
198
|
::Post.amoeba do
|
190
199
|
include_association :comments, if: :truthy?
|
191
200
|
end
|
192
|
-
expect { subject }.to change
|
201
|
+
expect { subject }.to change(Comment, :count).by(3)
|
193
202
|
end
|
194
203
|
|
195
|
-
it 'does not include
|
204
|
+
it 'does not include an association with a falsey condition' do
|
196
205
|
::Post.amoeba do
|
197
206
|
include_association :comments, if: :falsey?
|
198
207
|
end
|
199
|
-
expect { subject }.not_to change
|
208
|
+
expect { subject }.not_to change(Comment, :count)
|
200
209
|
end
|
201
210
|
|
202
|
-
it 'excludes
|
211
|
+
it 'excludes an association with a truthy condition' do
|
203
212
|
::Post.amoeba do
|
204
213
|
exclude_association :comments, if: :truthy?
|
205
214
|
end
|
206
|
-
expect { subject }.not_to change
|
215
|
+
expect { subject }.not_to change(Comment, :count)
|
207
216
|
end
|
208
217
|
|
209
|
-
it 'does not exclude
|
218
|
+
it 'does not exclude an association with a falsey condition' do
|
210
219
|
::Post.amoeba do
|
211
220
|
exclude_association :comments, if: :falsey?
|
212
221
|
end
|
213
|
-
expect { subject }.to change
|
222
|
+
expect { subject }.to change(Comment, :count).by(3)
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'includes associations from a given array with a truthy condition' do
|
226
|
+
::Post.amoeba do
|
227
|
+
include_association [:comments], if: :truthy?
|
228
|
+
end
|
229
|
+
expect { subject }.to change(Comment, :count).by(3)
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'does not include associations from a given array with a falsey condition' do
|
233
|
+
::Post.amoeba do
|
234
|
+
include_association [:comments], if: :falsey?
|
235
|
+
end
|
236
|
+
expect { subject }.not_to change(Comment, :count)
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'does exclude associations from a given array with a truthy condition' do
|
240
|
+
::Post.amoeba do
|
241
|
+
exclude_association [:comments], if: :truthy?
|
242
|
+
end
|
243
|
+
expect { subject }.not_to change(Comment, :count)
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'does not exclude associations from a given array with a falsey condition' do
|
247
|
+
::Post.amoeba do
|
248
|
+
exclude_association [:comments], if: :falsey?
|
249
|
+
end
|
250
|
+
expect { subject }.to change(Comment, :count).by(3)
|
214
251
|
end
|
215
252
|
end
|
216
253
|
|
217
254
|
context 'override' do
|
218
|
-
before
|
255
|
+
before do
|
219
256
|
::Image.fresh_amoeba
|
220
257
|
::Image.amoeba do
|
221
258
|
override ->(old, new) { new.product_id = 13 if old.filename == 'test.jpg' }
|
222
259
|
end
|
223
260
|
end
|
224
261
|
|
225
|
-
it '
|
262
|
+
it 'overrides fields' do
|
226
263
|
image = ::Image.create(filename: 'test.jpg', product_id: 12)
|
227
264
|
image_dup = image.amoeba_dup
|
228
265
|
expect(image_dup.save).to be_truthy
|
229
266
|
expect(image_dup.product_id).to eq(13)
|
230
267
|
end
|
231
268
|
|
232
|
-
it '
|
269
|
+
it 'does not override fields' do
|
233
270
|
image = ::Image.create(filename: 'test2.jpg', product_id: 12)
|
234
271
|
image_dup = image.amoeba_dup
|
235
272
|
expect(image_dup.save).to be_truthy
|
@@ -238,7 +275,7 @@ describe 'amoeba' do
|
|
238
275
|
end
|
239
276
|
|
240
277
|
context 'nullify' do
|
241
|
-
before
|
278
|
+
before do
|
242
279
|
::Image.fresh_amoeba
|
243
280
|
::Image.amoeba do
|
244
281
|
nullify :product_id
|
@@ -248,14 +285,14 @@ describe 'amoeba' do
|
|
248
285
|
let(:image) { ::Image.create(filename: 'test.jpg', product_id: 12) }
|
249
286
|
let(:image_dup) { image.amoeba_dup }
|
250
287
|
|
251
|
-
it '
|
288
|
+
it 'nullifies fields' do
|
252
289
|
expect(image_dup.save).to be_truthy
|
253
290
|
expect(image_dup.product_id).to be_nil
|
254
291
|
end
|
255
292
|
end
|
256
293
|
|
257
294
|
context 'strict propagate' do
|
258
|
-
it '
|
295
|
+
it 'calls #reset_amoeba' do
|
259
296
|
expect(::SuperBlackBox).to receive(:reset_amoeba).and_call_original
|
260
297
|
box = ::SuperBlackBox.create(title: 'Super Black Box', price: 9.99, length: 1, metal: '1')
|
261
298
|
new_box = box.amoeba_dup
|
@@ -284,13 +321,16 @@ describe 'amoeba' do
|
|
284
321
|
|
285
322
|
context 'preprocessing fields' do
|
286
323
|
subject { super_admin.amoeba_dup }
|
287
|
-
let(:super_admin) { ::SuperAdmin.create!(email: 'user@example.com', active: true, password: 'password') }
|
288
324
|
|
289
|
-
|
325
|
+
let(:super_admin) do
|
326
|
+
::SuperAdmin.create!(email: 'user@example.com', active: true, password: 'password')
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'accepts "set" to set false to attribute' do
|
290
330
|
expect(subject.active).to be false
|
291
331
|
end
|
292
332
|
|
293
|
-
it '
|
333
|
+
it 'skips "prepend" if it equal to false' do
|
294
334
|
expect(subject.password).to eq('password')
|
295
335
|
end
|
296
336
|
end
|
@@ -301,13 +341,15 @@ describe 'amoeba' do
|
|
301
341
|
it 'does not fail with a deep inheritance' do
|
302
342
|
sub_sub_product = BoxSubSubProduct.create(title: 'Awesome shoes')
|
303
343
|
another_product = BoxAnotherProduct.create(title: 'Cleaning product')
|
304
|
-
sub_sub_product.
|
344
|
+
sub_sub_product.update(box: box, another_product: another_product)
|
305
345
|
expect(box.sub_products.first.another_product.title).to eq('Cleaning product')
|
306
346
|
expect(box.amoeba_dup.sub_products.first.another_product.title).to eq('Cleaning product')
|
307
347
|
end
|
308
348
|
end
|
309
349
|
|
310
350
|
context 'inheritance extended' do
|
351
|
+
subject { stage.amoeba_dup }
|
352
|
+
|
311
353
|
let(:stage) do
|
312
354
|
stage = CustomStage.new(title: 'My Stage', external_id: 213)
|
313
355
|
stage.listeners.build(name: 'John')
|
@@ -318,19 +360,19 @@ describe 'amoeba' do
|
|
318
360
|
stage
|
319
361
|
end
|
320
362
|
|
321
|
-
|
322
|
-
|
323
|
-
it "contains parent association and own associations", :aggregate_failures do
|
363
|
+
it 'contains parent association and own associations', :aggregate_failures do
|
324
364
|
subject
|
325
|
-
expect { subject.save! }.to change(Listener, :count).by(2)
|
326
|
-
|
327
|
-
|
365
|
+
expect { subject.save! }.to change(Listener, :count).by(2)
|
366
|
+
.and change(Specialist, :count).by(1)
|
367
|
+
.and change(
|
368
|
+
CustomRule, :count
|
369
|
+
).by(1)
|
328
370
|
|
329
371
|
expect(subject.title).to eq 'My Stage'
|
330
372
|
expect(subject.external_id).to be_nil
|
331
|
-
expect(subject.listeners.find_by(name: 'John')).
|
332
|
-
expect(subject.listeners.find_by(name: 'Helen')).
|
333
|
-
expect(subject.specialists.find_by(name: 'Jack')).
|
373
|
+
expect(subject.listeners.find_by(name: 'John')).not_to be_nil
|
374
|
+
expect(subject.listeners.find_by(name: 'Helen')).not_to be_nil
|
375
|
+
expect(subject.specialists.find_by(name: 'Jack')).not_to be_nil
|
334
376
|
expect(subject.custom_rules.first.description).to eq 'Kill all humans'
|
335
377
|
end
|
336
378
|
end
|