amoeba 2.1.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.cane +4 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +17 -0
- data/.travis.yml +13 -5
- data/Appraisals +24 -0
- data/Gemfile +6 -4
- data/README.md +134 -44
- data/Rakefile +2 -2
- data/amoeba.gemspec +20 -15
- data/defaults.reek +11 -0
- data/gemfiles/activerecord_3.2.gemfile +17 -0
- data/gemfiles/activerecord_4.0.gemfile +17 -0
- data/gemfiles/activerecord_4.1.gemfile +17 -0
- data/gemfiles/activerecord_4.2.gemfile +17 -0
- data/gemfiles/activerecord_head.gemfile +23 -0
- data/lib/amoeba.rb +13 -522
- data/lib/amoeba/class_methods.rb +23 -0
- data/lib/amoeba/cloner.rb +168 -0
- data/lib/amoeba/config.rb +172 -0
- data/lib/amoeba/instance_methods.rb +37 -0
- data/lib/amoeba/macros.rb +14 -0
- data/lib/amoeba/macros/base.rb +26 -0
- data/lib/amoeba/macros/has_and_belongs_to_many.rb +19 -0
- data/lib/amoeba/macros/has_many.rb +42 -0
- data/lib/amoeba/macros/has_one.rb +15 -0
- data/lib/amoeba/version.rb +1 -1
- data/spec/lib/amoeba_spec.rb +180 -87
- data/spec/spec_helper.rb +23 -4
- data/spec/support/data.rb +73 -73
- data/spec/support/models.rb +132 -28
- data/spec/support/schema.rb +69 -42
- metadata +38 -29
- data/.ruby-version +0 -1
- data/gemfiles/Gemfile.activerecord-3.2.x +0 -11
- data/gemfiles/Gemfile.activerecord-4.0.x +0 -11
data/Rakefile
CHANGED
data/amoeba.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require
|
2
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'amoeba/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
6
|
+
s.name = 'amoeba'
|
7
7
|
s.version = Amoeba::VERSION
|
8
|
-
s.authors = [
|
9
|
-
s.email =
|
10
|
-
s.homepage =
|
11
|
-
s.license =
|
12
|
-
s.summary =
|
8
|
+
s.authors = ['Vaughn Draughon']
|
9
|
+
s.email = 'vaughn@rocksolidwebdesign.com'
|
10
|
+
s.homepage = 'http://github.com/rocksolidwebdesign/amoeba'
|
11
|
+
s.license = 'BSD'
|
12
|
+
s.summary = 'Easy copying of rails models and their child associations. '
|
13
13
|
|
14
14
|
s.description = <<-EOF
|
15
15
|
An extension to ActiveRecord to allow the duplication method to also copy associated children, with recursive support for nested of grandchildren. The behavior is controllable with a simple DSL both on your rails models and on the fly, i.e. per instance. Numerous configuration styles and preprocessing directives are included for power and flexibility. Supports preprocessing of field values to prepend strings such as "Copy of ", to nullify or process field values with regular expressions. Supports most association types including has_one :through and has_many :through.
|
@@ -17,18 +17,23 @@ An extension to ActiveRecord to allow the duplication method to also copy associ
|
|
17
17
|
Tags: copy child associations, copy nested children, copy associated child records, nested copy, copy associations, copy relations, copy relationships, duplicate associations, duplicate associated records, duplicate child records, duplicate children, copy all, duplicate all, clone child associations, clone nested children, clone associated child records, nested clone, clone associations, clone relations, clone relationships, cloning child associations, cloning nested children, cloning associated child records, deep_cloning, nested cloning, cloning associations, cloning relations, cloning relationships, cloning child associations, cloning nested children, cloning associated child records, nested cloning, cloning associations, cloning relations, cloning relationships, cloning child associations, cloning nested children, cloning associated child records, deep_cloning, nested cloning, cloning associations, cloning relations, cloning relationships, duplicate child associations, duplicate nested children, duplicate associated child records, nested duplicate, duplicate associations, duplicate relations, duplicate relationships, duplicate child associations, duplicate nested children, duplicate associated child records, deep_duplicate, nested duplicate, duplicate associations, duplicate relations, duplicate relationships, deep_copy, deep_clone, deep_cloning, deep clone, deep cloning, has_one, has_many, has_and_belongs_to_many
|
18
18
|
EOF
|
19
19
|
|
20
|
-
s.rubyforge_project =
|
20
|
+
s.rubyforge_project = 'amoeba'
|
21
21
|
|
22
22
|
s.files = `git ls-files`.split("\n")
|
23
23
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
-
s.require_paths = [
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
25
|
+
s.require_paths = ['lib']
|
26
26
|
|
27
27
|
# specify any dependencies here; for example:
|
28
|
-
s.add_development_dependency
|
29
|
-
s.add_development_dependency
|
28
|
+
s.add_development_dependency 'bundler', '>= 1.6.0'
|
29
|
+
s.add_development_dependency 'rspec', '>= 3.0.0'
|
30
30
|
|
31
|
-
|
31
|
+
if RUBY_PLATFORM == 'java'
|
32
|
+
s.add_development_dependency 'activerecord-jdbc-adapter', '~> 1.3.2'
|
33
|
+
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', '~> 1.3.2'
|
34
|
+
else
|
35
|
+
s.add_development_dependency 'sqlite3'
|
36
|
+
end
|
32
37
|
|
33
|
-
s.add_dependency 'activerecord', '>= 3.2.6'
|
38
|
+
s.add_dependency 'activerecord', '>= 3.2.6'
|
34
39
|
end
|
data/defaults.reek
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "activerecord", "~> 3.2.0"
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem "rake"
|
9
|
+
gem "coveralls", :require => false
|
10
|
+
end
|
11
|
+
|
12
|
+
group :local_development do
|
13
|
+
gem "pry"
|
14
|
+
gem "appraisal"
|
15
|
+
end
|
16
|
+
|
17
|
+
gemspec :path => "../"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "activerecord", "~> 4.0.0"
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem "rake"
|
9
|
+
gem "coveralls", :require => false
|
10
|
+
end
|
11
|
+
|
12
|
+
group :local_development do
|
13
|
+
gem "pry"
|
14
|
+
gem "appraisal"
|
15
|
+
end
|
16
|
+
|
17
|
+
gemspec :path => "../"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "activerecord", "~> 4.1.0"
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem "rake"
|
9
|
+
gem "coveralls", :require => false
|
10
|
+
end
|
11
|
+
|
12
|
+
group :local_development do
|
13
|
+
gem "pry"
|
14
|
+
gem "appraisal"
|
15
|
+
end
|
16
|
+
|
17
|
+
gemspec :path => "../"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "activerecord", "~> 4.2.0"
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem "rake"
|
9
|
+
gem "coveralls", :require => false
|
10
|
+
end
|
11
|
+
|
12
|
+
group :local_development do
|
13
|
+
gem "pry"
|
14
|
+
gem "appraisal"
|
15
|
+
end
|
16
|
+
|
17
|
+
gemspec :path => "../"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
git "git://github.com/rails/arel.git" do
|
6
|
+
gem "arel"
|
7
|
+
end
|
8
|
+
|
9
|
+
git "git://github.com/rails/rails.git" do
|
10
|
+
gem "activerecord"
|
11
|
+
end
|
12
|
+
|
13
|
+
group :development, :test do
|
14
|
+
gem "rake"
|
15
|
+
gem "coveralls", :require => false
|
16
|
+
end
|
17
|
+
|
18
|
+
group :local_development do
|
19
|
+
gem "pry"
|
20
|
+
gem "appraisal"
|
21
|
+
end
|
22
|
+
|
23
|
+
gemspec :path => "../"
|
data/lib/amoeba.rb
CHANGED
@@ -1,527 +1,18 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support/all'
|
3
|
+
require 'amoeba/version'
|
4
|
+
require 'amoeba/config'
|
5
|
+
require 'amoeba/macros'
|
6
|
+
require 'amoeba/macros/base'
|
7
|
+
require 'amoeba/macros/has_many'
|
8
|
+
require 'amoeba/macros/has_one'
|
9
|
+
require 'amoeba/macros/has_and_belongs_to_many'
|
10
|
+
require 'amoeba/cloner'
|
11
|
+
require 'amoeba/class_methods'
|
12
|
+
require 'amoeba/instance_methods'
|
3
13
|
|
4
14
|
module Amoeba
|
5
|
-
module Dsl # {{{
|
6
|
-
class Config
|
7
|
-
def initialize(parent)
|
8
|
-
@parent = parent
|
9
|
-
end
|
10
|
-
|
11
|
-
# Getters {{{
|
12
|
-
def upbringing
|
13
|
-
@raised ||= false
|
14
|
-
@raised
|
15
|
-
end
|
16
|
-
|
17
|
-
def enabled
|
18
|
-
@enabled ||= false
|
19
|
-
@enabled
|
20
|
-
end
|
21
|
-
|
22
|
-
def inherit
|
23
|
-
@inherit ||= false
|
24
|
-
@inherit
|
25
|
-
end
|
26
|
-
|
27
|
-
def do_preproc
|
28
|
-
@do_preproc ||= false
|
29
|
-
@do_preproc
|
30
|
-
end
|
31
|
-
|
32
|
-
def parenting
|
33
|
-
@parenting ||= false
|
34
|
-
@parenting
|
35
|
-
end
|
36
|
-
|
37
|
-
def known_macros
|
38
|
-
@known_macros ||= [:has_one, :has_many, :has_and_belongs_to_many]
|
39
|
-
@known_macros
|
40
|
-
end
|
41
|
-
|
42
|
-
def includes
|
43
|
-
@includes ||= []
|
44
|
-
@includes
|
45
|
-
end
|
46
|
-
|
47
|
-
def excludes
|
48
|
-
@excludes ||= []
|
49
|
-
@excludes
|
50
|
-
end
|
51
|
-
|
52
|
-
def clones
|
53
|
-
@clones ||= []
|
54
|
-
@clones
|
55
|
-
end
|
56
|
-
|
57
|
-
def customizations
|
58
|
-
@customizations ||= []
|
59
|
-
@customizations
|
60
|
-
end
|
61
|
-
|
62
|
-
def overrides
|
63
|
-
@overrides ||= []
|
64
|
-
@overrides
|
65
|
-
end
|
66
|
-
|
67
|
-
def null_fields
|
68
|
-
@null_fields ||= []
|
69
|
-
@null_fields
|
70
|
-
end
|
71
|
-
|
72
|
-
def coercions
|
73
|
-
@coercions ||= {}
|
74
|
-
@coercions
|
75
|
-
end
|
76
|
-
|
77
|
-
def prefixes
|
78
|
-
@prefixes ||= {}
|
79
|
-
@prefixes
|
80
|
-
end
|
81
|
-
|
82
|
-
def suffixes
|
83
|
-
@suffixes ||= {}
|
84
|
-
@suffixes
|
85
|
-
end
|
86
|
-
|
87
|
-
def regexes
|
88
|
-
@regexes ||= {}
|
89
|
-
@regexes
|
90
|
-
end
|
91
|
-
# }}}
|
92
|
-
|
93
|
-
# Setters (Config DSL) {{{
|
94
|
-
def enable
|
95
|
-
@enabled = true
|
96
|
-
end
|
97
|
-
|
98
|
-
def disable
|
99
|
-
@enabled = false
|
100
|
-
end
|
101
|
-
|
102
|
-
def raised(style=:submissive)
|
103
|
-
@raised = style
|
104
|
-
end
|
105
|
-
|
106
|
-
def propagate(style=:submissive)
|
107
|
-
@parenting ||= style
|
108
|
-
@inherit = true
|
109
|
-
end
|
110
|
-
|
111
|
-
def include_field(value=nil)
|
112
|
-
@enabled ||= true
|
113
|
-
@excludes = []
|
114
|
-
@includes ||= []
|
115
|
-
if value.is_a?(Array)
|
116
|
-
@includes = value
|
117
|
-
else
|
118
|
-
@includes << value if value
|
119
|
-
end
|
120
|
-
@includes
|
121
|
-
end
|
122
|
-
|
123
|
-
def exclude_field(value=nil)
|
124
|
-
@enabled ||= true
|
125
|
-
@includes = []
|
126
|
-
@excludes ||= []
|
127
|
-
if value.is_a?(Array)
|
128
|
-
@excludes = value
|
129
|
-
else
|
130
|
-
@excludes << value if value
|
131
|
-
end
|
132
|
-
@excludes
|
133
|
-
end
|
134
|
-
|
135
|
-
def clone(value=nil)
|
136
|
-
@enabled ||= true
|
137
|
-
@clones ||= []
|
138
|
-
if value.is_a?(Array)
|
139
|
-
@clones = value
|
140
|
-
else
|
141
|
-
@clones << value if value
|
142
|
-
end
|
143
|
-
@clones
|
144
|
-
end
|
145
|
-
|
146
|
-
def override(value=nil)
|
147
|
-
@do_preproc ||= true
|
148
|
-
@overrides ||= []
|
149
|
-
if value.is_a?(Array)
|
150
|
-
@overrides = value
|
151
|
-
else
|
152
|
-
@overrides << value if value
|
153
|
-
end
|
154
|
-
@overrides
|
155
|
-
end
|
156
|
-
|
157
|
-
def customize(value=nil)
|
158
|
-
@do_preproc ||= true
|
159
|
-
@customizations ||= []
|
160
|
-
if value.is_a?(Array)
|
161
|
-
@customizations = value
|
162
|
-
else
|
163
|
-
@customizations << value if value
|
164
|
-
end
|
165
|
-
@customizations
|
166
|
-
end
|
167
|
-
|
168
|
-
def recognize(value=nil)
|
169
|
-
@enabled ||= true
|
170
|
-
@known_macros ||= []
|
171
|
-
if value.is_a?(Array)
|
172
|
-
@known_macros = value
|
173
|
-
else
|
174
|
-
@known_macros << value if value
|
175
|
-
end
|
176
|
-
@known_macros
|
177
|
-
end
|
178
|
-
|
179
|
-
def nullify(value=nil)
|
180
|
-
@do_preproc ||= true
|
181
|
-
@null_fields ||= []
|
182
|
-
if value.is_a?(Array)
|
183
|
-
@null_fields = value
|
184
|
-
else
|
185
|
-
@null_fields << value if value
|
186
|
-
end
|
187
|
-
@null_fields
|
188
|
-
end
|
189
|
-
|
190
|
-
def set(defs=nil)
|
191
|
-
@do_preproc ||= true
|
192
|
-
@coercions ||= {}
|
193
|
-
if defs.is_a?(Array)
|
194
|
-
@coercions = {}
|
195
|
-
|
196
|
-
defs.each do |d|
|
197
|
-
d.each do |k,v|
|
198
|
-
@coercions[k] = v if v
|
199
|
-
end
|
200
|
-
end
|
201
|
-
else
|
202
|
-
defs.each do |k,v|
|
203
|
-
@coercions[k] = v if v
|
204
|
-
end
|
205
|
-
end
|
206
|
-
@coercions
|
207
|
-
end
|
208
|
-
|
209
|
-
def prepend(defs=nil)
|
210
|
-
@do_preproc ||= true
|
211
|
-
@prefixes ||= {}
|
212
|
-
if defs.is_a?(Array)
|
213
|
-
@prefixes = {}
|
214
|
-
|
215
|
-
defs.each do |d|
|
216
|
-
d.each do |k,v|
|
217
|
-
@prefixes[k] = v if v
|
218
|
-
end
|
219
|
-
end
|
220
|
-
else
|
221
|
-
defs.each do |k,v|
|
222
|
-
@prefixes[k] = v if v
|
223
|
-
end
|
224
|
-
end
|
225
|
-
@prefixes
|
226
|
-
end
|
227
|
-
|
228
|
-
def append(defs=nil)
|
229
|
-
@do_preproc ||= true
|
230
|
-
@suffixes ||= {}
|
231
|
-
if defs.is_a?(Array)
|
232
|
-
@suffixes = {}
|
233
|
-
|
234
|
-
defs.each do |d|
|
235
|
-
d.each do |k,v|
|
236
|
-
@suffixes[k] = v if v
|
237
|
-
end
|
238
|
-
end
|
239
|
-
else
|
240
|
-
defs.each do |k,v|
|
241
|
-
@suffixes[k] = v if v
|
242
|
-
end
|
243
|
-
end
|
244
|
-
@suffixes
|
245
|
-
end
|
246
|
-
|
247
|
-
def regex(defs=nil)
|
248
|
-
@do_preproc ||= true
|
249
|
-
@regexes ||= {}
|
250
|
-
if defs.is_a?(Array)
|
251
|
-
@regexes = {}
|
252
|
-
|
253
|
-
defs.each do |d|
|
254
|
-
d.each do |k,v|
|
255
|
-
@regexes[k] = v if v
|
256
|
-
end
|
257
|
-
end
|
258
|
-
else
|
259
|
-
defs.each do |k,v|
|
260
|
-
@regexes[k] = v if v
|
261
|
-
end
|
262
|
-
end
|
263
|
-
@regexes
|
264
|
-
end
|
265
|
-
# }}}
|
266
|
-
end
|
267
|
-
end # }}}
|
268
|
-
|
269
|
-
module ClassMethods
|
270
|
-
def amoeba(&block)
|
271
|
-
@config_block ||= block if block_given?
|
272
|
-
|
273
|
-
@config ||= Amoeba::Dsl::Config.new(self)
|
274
|
-
@config.instance_eval(&block) if block_given?
|
275
|
-
@config
|
276
|
-
end
|
277
|
-
|
278
|
-
def fresh_amoeba(&block)
|
279
|
-
@config_block = block if block_given?
|
280
|
-
|
281
|
-
@config = Amoeba::Dsl::Config.new(self)
|
282
|
-
@config.instance_eval(&block) if block_given?
|
283
|
-
@config
|
284
|
-
end
|
285
|
-
|
286
|
-
def amoeba_block
|
287
|
-
@config_block
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
module InstanceMethods
|
292
|
-
# Config Getters {{{
|
293
|
-
def amoeba_conf
|
294
|
-
self.class.amoeba
|
295
|
-
end
|
296
|
-
|
297
|
-
def amoeba_dup_options
|
298
|
-
@amoeba_dup_options
|
299
|
-
end
|
300
|
-
|
301
|
-
def has_parent_amoeba_conf?
|
302
|
-
self.class.superclass.respond_to?(:amoeba)
|
303
|
-
end
|
304
|
-
|
305
|
-
def parent_amoeba_conf
|
306
|
-
if has_parent_amoeba_conf?
|
307
|
-
self.class.superclass.amoeba
|
308
|
-
else
|
309
|
-
false
|
310
|
-
end
|
311
|
-
end
|
312
|
-
|
313
|
-
def amoeba_settings
|
314
|
-
self.class.amoeba_block
|
315
|
-
end
|
316
|
-
|
317
|
-
def has_parent_amoeba_settings?
|
318
|
-
self.class.superclass.respond_to?(:amoeba_block)
|
319
|
-
end
|
320
|
-
|
321
|
-
def parent_amoeba_settings
|
322
|
-
if has_parent_amoeba_conf?
|
323
|
-
self.class.superclass.amoeba_block
|
324
|
-
else
|
325
|
-
false
|
326
|
-
end
|
327
|
-
end
|
328
|
-
# }}}
|
329
|
-
|
330
|
-
def amoeba_dup(options={})
|
331
|
-
@result = self.dup()
|
332
|
-
@amoeba_dup_options = options
|
333
|
-
|
334
|
-
# Inherit Parent Settings {{{
|
335
|
-
if !amoeba_conf.enabled && parent_amoeba_conf.inherit
|
336
|
-
if amoeba_conf.upbringing
|
337
|
-
parenting_style = amoeba_conf.upbringing
|
338
|
-
else
|
339
|
-
parenting_style = parent_amoeba_conf.parenting
|
340
|
-
end
|
341
|
-
|
342
|
-
case parenting_style
|
343
|
-
when :strict
|
344
|
-
# parent settings only
|
345
|
-
self.class.fresh_amoeba(&parent_amoeba_settings)
|
346
|
-
when :relaxed
|
347
|
-
# parent takes precedence
|
348
|
-
self.class.amoeba(&parent_amoeba_settings)
|
349
|
-
when :submissive
|
350
|
-
# parent suggests things
|
351
|
-
# child does what it wants to anyway
|
352
|
-
child_settings = amoeba_settings
|
353
|
-
self.class.fresh_amoeba(&parent_amoeba_settings)
|
354
|
-
self.class.amoeba(&child_settings)
|
355
|
-
end
|
356
|
-
end
|
357
|
-
# }}}
|
358
|
-
|
359
|
-
# Run Amoeba {{{
|
360
|
-
# pramoeba_conf.overridesepend any extra strings to indicate uniqueness of the new record(s)
|
361
|
-
if amoeba_conf.overrides.length > 0
|
362
|
-
amoeba_conf.overrides.each do |block|
|
363
|
-
block.call(self, @result)
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
if amoeba_conf.enabled
|
368
|
-
# Deep Clone Settings {{{
|
369
|
-
amoeba_conf.clones.each do |clone_field|
|
370
|
-
r = self.class.reflect_on_association clone_field
|
371
|
-
|
372
|
-
# if this is a has many through and we're gonna deep
|
373
|
-
# copy the child records, exclude the regular join
|
374
|
-
# table from copying so we don't end up with the new
|
375
|
-
# and old children on the copy
|
376
|
-
if r.macro == :has_many && r.is_a?(ActiveRecord::Reflection::ThroughReflection)
|
377
|
-
amoeba_conf.exclude_field r.options[:through]
|
378
|
-
end
|
379
|
-
end
|
380
|
-
# }}}
|
381
|
-
|
382
|
-
# Inclusive Style {{{
|
383
|
-
if amoeba_conf.includes.count > 0
|
384
|
-
amoeba_conf.includes.each do |i|
|
385
|
-
r = self.class.reflect_on_association i
|
386
|
-
amo_process_association(i, r)
|
387
|
-
end
|
388
|
-
# }}}
|
389
|
-
# Exclusive Style {{{
|
390
|
-
elsif amoeba_conf.excludes.count > 0
|
391
|
-
self.class.reflections.each do |r|
|
392
|
-
if not amoeba_conf.excludes.include?(r[0])
|
393
|
-
amo_process_association(r[0], r[1])
|
394
|
-
end
|
395
|
-
end
|
396
|
-
# }}}
|
397
|
-
# Indiscriminate Style {{{
|
398
|
-
else
|
399
|
-
self.class.reflections.each do |r|
|
400
|
-
amo_process_association(r[0], r[1])
|
401
|
-
end
|
402
|
-
end
|
403
|
-
# }}}
|
404
|
-
end
|
405
|
-
|
406
|
-
if amoeba_conf.do_preproc
|
407
|
-
amo_preprocess_parent_copy
|
408
|
-
end
|
409
|
-
# }}}
|
410
|
-
|
411
|
-
@result
|
412
|
-
end
|
413
|
-
|
414
|
-
private
|
415
|
-
# Copy Children {{{
|
416
|
-
def amo_process_association(relation_name, settings)
|
417
|
-
if not amoeba_conf.known_macros.include?(settings.macro)
|
418
|
-
return
|
419
|
-
end
|
420
|
-
|
421
|
-
case settings.macro
|
422
|
-
when :has_one
|
423
|
-
if settings.is_a?(ActiveRecord::Reflection::ThroughReflection)
|
424
|
-
return
|
425
|
-
end
|
426
|
-
|
427
|
-
old_obj = self.send(relation_name)
|
428
|
-
|
429
|
-
if not old_obj.nil?
|
430
|
-
copy_of_obj = old_obj.amoeba_dup(amoeba_dup_options)
|
431
|
-
copy_of_obj[:"#{settings.foreign_key}"] = nil
|
432
|
-
|
433
|
-
@result.send(:"#{relation_name}=", copy_of_obj)
|
434
|
-
end
|
435
|
-
when :has_many
|
436
|
-
clone = amoeba_conf.clones.include?(:"#{relation_name}")
|
437
|
-
|
438
|
-
# this could be DRYed up for better readability by
|
439
|
-
# duplicating the loop code, but I'm duplicating the
|
440
|
-
# loops to avoid that extra check on each iteration
|
441
|
-
if clone
|
442
|
-
# This is a M:M "has many through" where we
|
443
|
-
# actually copy and reassociate the new children
|
444
|
-
# rather than only maintaining the associations
|
445
|
-
self.send(relation_name).each do |old_obj|
|
446
|
-
|
447
|
-
copy_of_obj = old_obj.amoeba_dup
|
448
|
-
|
449
|
-
# associate this new child to the new parent object
|
450
|
-
@result.send(relation_name) << copy_of_obj
|
451
|
-
end
|
452
|
-
else
|
453
|
-
# This is a regular 1:M "has many"
|
454
|
-
#
|
455
|
-
# copying the children of the regular has many will
|
456
|
-
# effectively do what is desired anyway, the through
|
457
|
-
# association is really just for convenience usage
|
458
|
-
# on the model
|
459
|
-
return if settings.is_a?(ActiveRecord::Reflection::ThroughReflection)
|
460
|
-
|
461
|
-
self.send(relation_name).each do |old_obj|
|
462
|
-
copy_of_obj = old_obj.amoeba_dup(amoeba_dup_options)
|
463
|
-
copy_of_obj[:"#{settings.foreign_key}"] = nil
|
464
|
-
|
465
|
-
# associate this new child to the new parent object
|
466
|
-
@result.send(relation_name) << copy_of_obj
|
467
|
-
end
|
468
|
-
end
|
469
|
-
|
470
|
-
when :has_and_belongs_to_many
|
471
|
-
clone = amoeba_conf.clones.include?(relation_name)
|
472
|
-
|
473
|
-
if clone
|
474
|
-
self.send(relation_name).each do |old_obj|
|
475
|
-
copy_of_obj = old_obj.amoeba_dup
|
476
|
-
|
477
|
-
# associate this new child to the new parent object
|
478
|
-
@result.send(relation_name) << copy_of_obj
|
479
|
-
end
|
480
|
-
else
|
481
|
-
self.send(relation_name).each do |old_obj|
|
482
|
-
# associate this new child to the new parent object
|
483
|
-
@result.send(relation_name) << old_obj
|
484
|
-
end
|
485
|
-
end
|
486
|
-
end
|
487
|
-
end
|
488
|
-
# }}}
|
489
|
-
|
490
|
-
# Field Preprocessor {{{
|
491
|
-
def amo_preprocess_parent_copy
|
492
|
-
# nullify any fields the user has configured
|
493
|
-
amoeba_conf.null_fields.each do |n|
|
494
|
-
@result[n] = nil
|
495
|
-
end
|
496
|
-
|
497
|
-
# prepend any extra strings to indicate uniqueness of the new record(s)
|
498
|
-
amoeba_conf.coercions.each do |field,coercion|
|
499
|
-
@result[field] = "#{coercion}"
|
500
|
-
end
|
501
|
-
|
502
|
-
# prepend any extra strings to indicate uniqueness of the new record(s)
|
503
|
-
amoeba_conf.prefixes.each do |field,prefix|
|
504
|
-
@result[field] = "#{prefix}#{@result[field]}"
|
505
|
-
end
|
506
|
-
|
507
|
-
# postpend any extra strings to indicate uniqueness of the new record(s)
|
508
|
-
amoeba_conf.suffixes.each do |field,suffix|
|
509
|
-
@result[field] = "#{@result[field]}#{suffix}"
|
510
|
-
end
|
511
|
-
|
512
|
-
# regex andy fields that need changing
|
513
|
-
amoeba_conf.regexes.each do |field,action|
|
514
|
-
@result[field].gsub!(action[:replace], action[:with])
|
515
|
-
end
|
516
|
-
|
517
|
-
# prepend any extra strings to indicate uniqueness of the new record(s)
|
518
|
-
amoeba_conf.customizations.each do |block|
|
519
|
-
block.call(self, @result)
|
520
|
-
end
|
521
|
-
end
|
522
|
-
# }}}
|
523
|
-
end
|
524
15
|
end
|
525
16
|
|
526
|
-
ActiveRecord::Base.send :extend,
|
17
|
+
ActiveRecord::Base.send :extend, Amoeba::ClassMethods
|
527
18
|
ActiveRecord::Base.send :include, Amoeba::InstanceMethods
|