amoeba 1.2.1 → 3.2.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 +7 -0
- data/.cane +4 -0
- data/.gitignore +4 -1
- data/.rspec +2 -0
- data/.rubocop.yml +17 -0
- data/.travis.yml +110 -0
- data/Appraisals +76 -0
- data/Gemfile +11 -3
- data/README.md +763 -529
- data/Rakefile +6 -1
- data/amoeba.gemspec +20 -15
- data/defaults.reek +11 -0
- data/gemfiles/activerecord_4.2.gemfile +18 -0
- data/gemfiles/activerecord_5.0.gemfile +18 -0
- data/gemfiles/activerecord_5.1.gemfile +18 -0
- data/gemfiles/activerecord_5.2.gemfile +18 -0
- data/gemfiles/activerecord_6.0.gemfile +18 -0
- data/gemfiles/activerecord_6.1.gemfile +18 -0
- data/gemfiles/activerecord_head.gemfile +24 -0
- data/gemfiles/jruby_activerecord_6.1.gemfile +19 -0
- data/gemfiles/jruby_activerecord_head.gemfile +28 -0
- data/lib/amoeba.rb +13 -517
- data/lib/amoeba/class_methods.rb +28 -0
- data/lib/amoeba/cloner.rb +172 -0
- data/lib/amoeba/config.rb +182 -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 +336 -111
- data/spec/spec_helper.rb +24 -3
- data/spec/support/data.rb +65 -84
- data/spec/support/models.rb +241 -25
- data/spec/support/schema.rb +102 -41
- metadata +63 -70
- data/.rvmrc +0 -1
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,29 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
4
|
+
SimpleCov::Formatter::HTMLFormatter,
|
5
|
+
Coveralls::SimpleCov::Formatter
|
6
|
+
])
|
7
|
+
SimpleCov.start do
|
8
|
+
add_filter 'spec'
|
9
|
+
minimum_coverage(76)
|
10
|
+
end
|
11
|
+
require 'active_record'
|
1
12
|
require 'amoeba'
|
2
13
|
|
3
|
-
|
4
|
-
|
14
|
+
adapter = if defined?(JRuby)
|
15
|
+
require 'activerecord-jdbcsqlite3-adapter'
|
16
|
+
'jdbcsqlite3'
|
17
|
+
else
|
18
|
+
require 'sqlite3'
|
19
|
+
'sqlite3'
|
20
|
+
end
|
21
|
+
|
22
|
+
ActiveRecord::Base.establish_connection(adapter: adapter, database: ':memory:')
|
23
|
+
|
24
|
+
::RSpec.configure do |config|
|
25
|
+
config.order = :default
|
26
|
+
end
|
5
27
|
|
6
28
|
load File.dirname(__FILE__) + '/support/schema.rb'
|
7
29
|
load File.dirname(__FILE__) + '/support/models.rb'
|
8
|
-
load File.dirname(__FILE__) + '/support/data.rb'
|
data/spec/support/data.rb
CHANGED
@@ -1,108 +1,77 @@
|
|
1
|
-
u1 = User.create(:name => "Robert Johnson", :email => "bob@crossroads.com")
|
2
|
-
u2 = User.create(:name => "Miles Davis", :email => "miles@kindofblue.com")
|
3
1
|
|
4
|
-
|
5
|
-
|
2
|
+
u1 = User.create(name: 'Robert Johnson', email: 'bob@crossroads.com')
|
3
|
+
u2 = User.create(name: 'Miles Davis', email: 'miles@kindofblue.com')
|
6
4
|
|
7
|
-
|
5
|
+
a1 = Author.create(full_name: 'Kermit The Vonnegut', nickname: 'kvsoitgoes')
|
6
|
+
a2 = Author.create(full_name: 'Arthur Sees Clarck', nickname: 'strangewater')
|
7
|
+
|
8
|
+
t = Topic.create(title: 'Ponies', description: 'Lets talk about my ponies.')
|
8
9
|
|
9
10
|
# First Post {{{
|
10
|
-
p1 = t.posts.create(:
|
11
|
-
f1 = p1.create_post_config(:
|
12
|
-
a1 = p1.create_account(:
|
13
|
-
h1 = p1.account.create_history(:
|
14
|
-
c1 = p1.comments.create(:
|
15
|
-
c1.ratings.create(:
|
16
|
-
c1.ratings.create(:num_stars => 5)
|
17
|
-
c1.ratings.create(:num_stars => 4)
|
18
|
-
c1.ratings.create(:num_stars => 3)
|
19
|
-
c1.ratings.create(:num_stars => 5)
|
20
|
-
c1.ratings.create(:num_stars => 5)
|
21
|
-
|
22
|
-
c2 = p1.comments.create(:contents => "I hate it!", :nerf => "whapaow")
|
23
|
-
c2.ratings.create(:num_stars => 3)
|
24
|
-
c2.ratings.create(:num_stars => 1)
|
25
|
-
c2.ratings.create(:num_stars => 4)
|
26
|
-
c2.ratings.create(:num_stars => 1)
|
27
|
-
c2.ratings.create(:num_stars => 1)
|
28
|
-
c2.ratings.create(:num_stars => 2)
|
29
|
-
|
30
|
-
c3 = p1.comments.create(:contents => "kthxbbq!!11!!!1!eleven!!", :nerf => "bonk")
|
31
|
-
c3.ratings.create(:num_stars => 0)
|
32
|
-
c3.ratings.create(:num_stars => 0)
|
33
|
-
c3.ratings.create(:num_stars => 1)
|
34
|
-
c3.ratings.create(:num_stars => 2)
|
35
|
-
c3.ratings.create(:num_stars => 1)
|
36
|
-
c3.ratings.create(:num_stars => 0)
|
37
|
-
|
38
|
-
t1 = Tag.create(:value => "funny")
|
39
|
-
t2 = Tag.create(:value => "wtf")
|
40
|
-
t3 = Tag.create(:value => "cats")
|
41
|
-
|
42
|
-
p1.tags << t1
|
43
|
-
p1.tags << t2
|
44
|
-
p1.tags << t3
|
45
|
-
p1.save
|
11
|
+
p1 = t.posts.create(owner: u1, author: a1, title: 'My little pony', contents: 'Lorum ipsum dolor rainbow bright. I like dogs, dogs are awesome.')
|
12
|
+
f1 = p1.create_post_config(is_visible: true, is_open: false, password: 'abcdefg123')
|
13
|
+
a1 = p1.create_account(title: 'Foo')
|
14
|
+
h1 = p1.account.create_history(some_stuff: 'Bar')
|
15
|
+
c1 = p1.comments.create(contents: 'I love it!', nerf: 'ratatat')
|
16
|
+
[5, 5, 4, 3, 5, 5].each { |stars| c1.ratings.create(num_stars: stars) }
|
46
17
|
|
47
|
-
|
48
|
-
|
49
|
-
w3 = Widget.create(:value => "Share & Like")
|
18
|
+
c2 = p1.comments.create(contents: 'I hate it!', nerf: 'whapaow')
|
19
|
+
[3, 1, 4, 1, 1, 2].each { |stars| c2.ratings.create(num_stars: stars) }
|
50
20
|
|
51
|
-
p1.
|
52
|
-
|
53
|
-
|
54
|
-
p1.
|
21
|
+
c3 = p1.comments.create(contents: 'kthxbbq!!11!!!1!eleven!!', nerf: 'bonk')
|
22
|
+
[0, 0, 1, 2, 1, 0].each { |stars| c3.ratings.create(num_stars: stars) }
|
23
|
+
|
24
|
+
%w(funny wtf cats).each { |value| p1.tags << Tag.create(value: value) }
|
25
|
+
|
26
|
+
['My Sidebar', 'Photo Gallery', 'Share & Like'].each { |value| p1.widgets << Widget.create(value: value) }
|
55
27
|
|
56
|
-
|
57
|
-
n2 = Note.create(:value => "You've been warned")
|
58
|
-
n3 = Note.create(:value => "Don't forget")
|
28
|
+
['This is important', "You've been warned", "Don't forget"].each { |value| p1.notes << Note.create(value: value) }
|
59
29
|
|
60
|
-
p1.notes << n1
|
61
|
-
p1.notes << n2
|
62
|
-
p1.notes << n3
|
63
30
|
p1.save
|
64
31
|
|
65
|
-
c1 = Category.create(:
|
66
|
-
c2 = Category.create(:
|
67
|
-
c3 = Category.create(:
|
32
|
+
c1 = Category.create(title: 'Umbrellas', description: 'Clown fart')
|
33
|
+
c2 = Category.create(title: 'Widgets', description: 'Humpty dumpty')
|
34
|
+
c3 = Category.create(title: 'Wombats', description: 'Slushy mushy')
|
68
35
|
|
69
|
-
s1 = Supercat.create(:
|
70
|
-
s2 = Supercat.create(:
|
71
|
-
s3 = Supercat.create(:
|
36
|
+
s1 = Supercat.create(post: p1, category: c1, ramblings: 'zomg', other_ramblings: 'nerp')
|
37
|
+
s2 = Supercat.create(post: p1, category: c2, ramblings: 'why', other_ramblings: 'narp')
|
38
|
+
s3 = Supercat.create(post: p1, category: c3, ramblings: 'ohnoes', other_ramblings: 'blap')
|
72
39
|
|
73
|
-
s1.superkittens.create(:
|
74
|
-
s1.superkittens.create(:
|
75
|
-
s1.superkittens.create(:
|
40
|
+
s1.superkittens.create(value: 'Fluffy')
|
41
|
+
s1.superkittens.create(value: 'Buffy')
|
42
|
+
s1.superkittens.create(value: 'Fuzzy')
|
76
43
|
|
77
|
-
s2.superkittens.create(:
|
78
|
-
s2.superkittens.create(:
|
79
|
-
s2.superkittens.create(:
|
44
|
+
s2.superkittens.create(value: 'Hairball')
|
45
|
+
s2.superkittens.create(value: 'Crosseye')
|
46
|
+
s2.superkittens.create(value: 'Spot')
|
80
47
|
|
81
|
-
s3.superkittens.create(:
|
82
|
-
s3.superkittens.create(:
|
83
|
-
s3.superkittens.create(:
|
48
|
+
s3.superkittens.create(value: 'Dopey')
|
49
|
+
s3.superkittens.create(value: 'Sneezy')
|
50
|
+
s3.superkittens.create(value: 'Sleepy')
|
51
|
+
|
52
|
+
p1.custom_things.create([{ value: [1, 2] }, { value: [] }, { value: [78] }])
|
84
53
|
# }}}
|
85
54
|
|
86
55
|
# Product {{{
|
87
|
-
product1 = Product.create(:
|
88
|
-
shirt1 = Shirt.create(:
|
89
|
-
necklace1 = Necklace.create(:
|
56
|
+
product1 = Product.create(title: 'Sticky Notes 5-Pak', price: 5.99, weight: 0.56)
|
57
|
+
shirt1 = Shirt.create(title: 'Fancy Shirt', price: 48.95, sleeve: 32, collar: 15.5)
|
58
|
+
necklace1 = Necklace.create(title: 'Pearl Necklace', price: 2995.99, length: 18, metal: '14k')
|
90
59
|
|
91
|
-
img1 = product1.images.create(:
|
92
|
-
img2 = product1.images.create(:
|
60
|
+
img1 = product1.images.create(filename: 'sticky.jpg')
|
61
|
+
img2 = product1.images.create(filename: 'notes.jpg')
|
93
62
|
|
94
|
-
img1 = shirt1.images.create(:
|
95
|
-
img2 = shirt1.images.create(:
|
63
|
+
img1 = shirt1.images.create(filename: '02948u31.jpg')
|
64
|
+
img2 = shirt1.images.create(filename: 'zsif8327.jpg')
|
96
65
|
|
97
|
-
img1 = necklace1.images.create(:
|
98
|
-
img2 = necklace1.images.create(:
|
66
|
+
img1 = necklace1.images.create(filename: 'ae02x9f1.jpg')
|
67
|
+
img2 = necklace1.images.create(filename: 'cba9f912.jpg')
|
99
68
|
|
100
|
-
office = Section.create(:
|
101
|
-
supplies = Section.create(:
|
102
|
-
mens = Section.create(:
|
103
|
-
apparel = Section.create(:
|
104
|
-
accessories = Section.create(:
|
105
|
-
jewelry = Section.create(:
|
69
|
+
office = Section.create(name: 'Office', num_employees: 2, total_sales: '1234.56')
|
70
|
+
supplies = Section.create(name: 'Supplies', num_employees: 1, total_sales: '543.21')
|
71
|
+
mens = Section.create(name: 'Mens', num_employees: 3, total_sales: '11982.63')
|
72
|
+
apparel = Section.create(name: 'Apparel', num_employees: 5, total_sales: '1315.20')
|
73
|
+
accessories = Section.create(name: 'Accessories', num_employees: 1, total_sales: '8992.34')
|
74
|
+
jewelry = Section.create(name: 'Jewelry', num_employees: 3, total_sales: '25481.77')
|
106
75
|
|
107
76
|
product1.sections << office
|
108
77
|
product1.sections << supplies
|
@@ -115,4 +84,16 @@ shirt1.save
|
|
115
84
|
necklace1.sections << jewelry
|
116
85
|
necklace1.sections << accessories
|
117
86
|
necklace1.save
|
87
|
+
|
88
|
+
|
89
|
+
company = Company.create(name:'ABC Industries')
|
90
|
+
employee = company.employees.create(name:'Joe',ssn:'1111111111',salary:10000.0)
|
91
|
+
employee_address = employee.addresses.create(street: '123 My Street',unit:'103',city:'Hollywood',state:'CA',zip:'90210')
|
92
|
+
employee_address_2 = employee.addresses.create(street: '124 My Street',unit:'103',city:'Follywood',state:'CA',zip:'90210')
|
93
|
+
employee_photo = employee.photos.create(name: 'Portrait', size: 12345)
|
94
|
+
customer = company.customers.create(email:'my@email.address',password:'password')
|
95
|
+
customer_address = customer.addresses.create(street: '321 My Street',unit:'301',city:'Bollywood',state:'IN',zip:'11111')
|
96
|
+
customer_address_2 = customer.addresses.create(street: '321 My Drive',unit:'311',city:'Mollywood',state:'IN',zip:'21111')
|
97
|
+
customer_photo = customer.photos.create(name: 'Mug Shot', size: 54321)
|
98
|
+
|
118
99
|
# }}}
|
data/spec/support/models.rb
CHANGED
@@ -7,7 +7,7 @@ class User < ActiveRecord::Base
|
|
7
7
|
end
|
8
8
|
|
9
9
|
class Author < ActiveRecord::Base
|
10
|
-
has_many :posts, :
|
10
|
+
has_many :posts, inverse_of: :author
|
11
11
|
amoeba do
|
12
12
|
enable
|
13
13
|
end
|
@@ -15,16 +15,17 @@ end
|
|
15
15
|
|
16
16
|
class Post < ActiveRecord::Base
|
17
17
|
belongs_to :topic
|
18
|
-
belongs_to :owner, :
|
19
|
-
belongs_to :author, :
|
18
|
+
belongs_to :owner, class_name: 'User'
|
19
|
+
belongs_to :author, inverse_of: :posts
|
20
20
|
has_one :post_config
|
21
21
|
has_one :account
|
22
|
-
has_one :history, :
|
22
|
+
has_one :history, through: :account
|
23
23
|
has_many :comments
|
24
24
|
has_many :supercats
|
25
|
-
has_many :categories, :
|
25
|
+
has_many :categories, through: :supercats
|
26
26
|
has_many :post_widgets
|
27
|
-
has_many :widgets, :
|
27
|
+
has_many :widgets, through: :post_widgets
|
28
|
+
has_many :custom_things
|
28
29
|
has_and_belongs_to_many :tags
|
29
30
|
has_and_belongs_to_many :notes
|
30
31
|
|
@@ -34,13 +35,13 @@ class Post < ActiveRecord::Base
|
|
34
35
|
amoeba do
|
35
36
|
enable
|
36
37
|
clone [:widgets, :notes]
|
37
|
-
prepend :
|
38
|
-
append :
|
39
|
-
regex :
|
38
|
+
prepend title: 'Copy of '
|
39
|
+
append contents: ' (copied version)'
|
40
|
+
regex contents: { replace: /dog/, with: 'cat' }
|
40
41
|
customize([
|
41
|
-
lambda do |orig_obj,copy_of_obj|
|
42
|
+
lambda do |orig_obj, copy_of_obj|
|
42
43
|
orig_obj.comments.each do |oc|
|
43
|
-
if oc.nerf ==
|
44
|
+
if oc.nerf == 'ratatat'
|
44
45
|
hash = oc.attributes
|
45
46
|
hash[:id] = nil
|
46
47
|
hash[:post_id] = nil
|
@@ -52,14 +53,14 @@ class Post < ActiveRecord::Base
|
|
52
53
|
end
|
53
54
|
end
|
54
55
|
end,
|
55
|
-
lambda do |orig_obj,copy_of_obj|
|
56
|
+
lambda do |orig_obj, copy_of_obj|
|
56
57
|
orig_obj.comments.each do |oc|
|
57
|
-
if oc.nerf ==
|
58
|
+
if oc.nerf == 'bonk'
|
58
59
|
hash = oc.attributes
|
59
60
|
hash[:id] = nil
|
60
61
|
hash[:post_id] = nil
|
61
62
|
hash[:contents] = nil
|
62
|
-
hash[:nerf] =
|
63
|
+
hash[:nerf] = 'bonkers'
|
63
64
|
|
64
65
|
cc = Comment.new(hash)
|
65
66
|
|
@@ -69,10 +70,49 @@ class Post < ActiveRecord::Base
|
|
69
70
|
end
|
70
71
|
])
|
71
72
|
end
|
73
|
+
|
74
|
+
def truthy?
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def falsey?
|
79
|
+
false
|
80
|
+
end
|
81
|
+
|
82
|
+
class << self
|
83
|
+
def tag_count
|
84
|
+
ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS tag_count FROM posts_tags')['tag_count']
|
85
|
+
end
|
86
|
+
|
87
|
+
def note_count
|
88
|
+
ActiveRecord::Base.connection.select_one('SELECT COUNT(*) AS note_count FROM notes_posts')['note_count']
|
89
|
+
end
|
90
|
+
end
|
72
91
|
end
|
73
92
|
|
74
93
|
class CustomThing < ActiveRecord::Base
|
75
94
|
belongs_to :post
|
95
|
+
|
96
|
+
class ArrayPack
|
97
|
+
def self.load(str)
|
98
|
+
return [] unless str.present?
|
99
|
+
return str if str.is_a?(Array)
|
100
|
+
str.split(',').map(&:to_i)
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.dump(int_array)
|
104
|
+
return '' unless int_array.present?
|
105
|
+
int_array.join(',')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
serialize :value, ArrayPack
|
110
|
+
|
111
|
+
before_create :hydrate_me
|
112
|
+
|
113
|
+
def hydrate_me
|
114
|
+
self.value = value
|
115
|
+
end
|
76
116
|
end
|
77
117
|
|
78
118
|
class Account < ActiveRecord::Base
|
@@ -90,12 +130,12 @@ end
|
|
90
130
|
|
91
131
|
class Category < ActiveRecord::Base
|
92
132
|
has_many :supercats
|
93
|
-
has_many :posts, :
|
133
|
+
has_many :posts, through: :supercats
|
94
134
|
|
95
135
|
amoeba do
|
96
136
|
enable
|
97
|
-
prepend :
|
98
|
-
set :
|
137
|
+
prepend ramblings: 'Copy of '
|
138
|
+
set other_ramblings: 'La la la'
|
99
139
|
end
|
100
140
|
end
|
101
141
|
|
@@ -105,9 +145,9 @@ class Supercat < ActiveRecord::Base
|
|
105
145
|
has_many :superkittens
|
106
146
|
|
107
147
|
amoeba do
|
108
|
-
|
109
|
-
prepend :
|
110
|
-
set :
|
148
|
+
include_association :superkittens
|
149
|
+
prepend ramblings: 'Copy of '
|
150
|
+
set other_ramblings: 'La la la'
|
111
151
|
end
|
112
152
|
end
|
113
153
|
|
@@ -125,7 +165,7 @@ class Comment < ActiveRecord::Base
|
|
125
165
|
has_many :reviews
|
126
166
|
|
127
167
|
amoeba do
|
128
|
-
|
168
|
+
exclude_association :reviews
|
129
169
|
end
|
130
170
|
end
|
131
171
|
|
@@ -139,7 +179,7 @@ end
|
|
139
179
|
|
140
180
|
class Widget < ActiveRecord::Base
|
141
181
|
has_many :post_widgets
|
142
|
-
has_many :posts, :
|
182
|
+
has_many :posts, through: :post_widgets
|
143
183
|
end
|
144
184
|
|
145
185
|
class PostWidget < ActiveRecord::Base
|
@@ -160,10 +200,16 @@ class Product < ActiveRecord::Base
|
|
160
200
|
has_many :images
|
161
201
|
has_and_belongs_to_many :sections
|
162
202
|
|
203
|
+
SECTION_COUNT_QUERY = 'SELECT COUNT(*) AS section_count FROM products_sections WHERE product_id = ?'.freeze
|
204
|
+
|
163
205
|
amoeba do
|
164
206
|
enable
|
165
207
|
propagate
|
166
208
|
end
|
209
|
+
|
210
|
+
def section_count
|
211
|
+
ActiveRecord::Base.connection.select_one(SECTION_COUNT_QUERY, id)['section_count']
|
212
|
+
end
|
167
213
|
end
|
168
214
|
|
169
215
|
class Section < ActiveRecord::Base
|
@@ -179,21 +225,191 @@ class Shirt < Product
|
|
179
225
|
end
|
180
226
|
|
181
227
|
class Necklace < Product
|
228
|
+
# Strange bug on rbx
|
229
|
+
if defined?(::Rubinius)
|
230
|
+
after_initialize :set_type
|
231
|
+
|
232
|
+
def set_type
|
233
|
+
self.type = 'Necklace'
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
182
237
|
amoeba do
|
183
238
|
raised :relaxed
|
184
239
|
end
|
185
240
|
end
|
186
241
|
|
242
|
+
class BlackBox < Product
|
243
|
+
amoeba do
|
244
|
+
propagate :strict
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
class SuperBlackBox < BlackBox
|
249
|
+
end
|
250
|
+
|
187
251
|
# Polymorphism
|
188
252
|
class Address < ActiveRecord::Base
|
189
|
-
belongs_to :addressable, :
|
253
|
+
belongs_to :addressable, polymorphic: true
|
254
|
+
|
255
|
+
amoeba do
|
256
|
+
enable
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
class Photo < ActiveRecord::Base
|
261
|
+
belongs_to :imageable, polymorphic: true
|
262
|
+
|
263
|
+
amoeba do
|
264
|
+
customize(lambda { |original_photo,new_photo|
|
265
|
+
new_photo.name = original_photo.name.to_s + ' Copy'
|
266
|
+
})
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
class Company < ActiveRecord::Base
|
271
|
+
has_many :employees
|
272
|
+
has_many :customers
|
273
|
+
|
274
|
+
amoeba do
|
275
|
+
include_associations :employees,
|
276
|
+
:customers
|
277
|
+
end
|
190
278
|
end
|
191
279
|
|
192
280
|
class Employee < ActiveRecord::Base
|
193
|
-
has_many :addresses, :
|
281
|
+
has_many :addresses, as: :addressable
|
282
|
+
has_many :photos, as: :imageable
|
283
|
+
belongs_to :company
|
284
|
+
|
285
|
+
amoeba do
|
286
|
+
include_associations [:addresses, :photos]
|
287
|
+
end
|
288
|
+
|
194
289
|
end
|
195
290
|
|
196
291
|
class Customer < ActiveRecord::Base
|
197
|
-
has_many :addresses, :
|
292
|
+
has_many :addresses, as: :addressable
|
293
|
+
has_many :photos, as: :imageable
|
294
|
+
belongs_to :company
|
295
|
+
|
296
|
+
amoeba do
|
297
|
+
enable
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Remapping and Method
|
302
|
+
|
303
|
+
class MetalObject < ActiveRecord::Base
|
304
|
+
end
|
305
|
+
|
306
|
+
class ObjectPrototype < MetalObject
|
307
|
+
has_many :subobject_prototypes, foreign_key: :parent_id
|
308
|
+
|
309
|
+
amoeba do
|
310
|
+
enable
|
311
|
+
through :become_real
|
312
|
+
remapper :remap_subobjects
|
313
|
+
end
|
314
|
+
|
315
|
+
def become_real
|
316
|
+
self.dup.becomes RealObject
|
317
|
+
end
|
318
|
+
|
319
|
+
def remap_subobjects(relation_name)
|
320
|
+
:subobjects if relation_name == :subobject_prototypes
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
class RealObject < MetalObject
|
325
|
+
has_many :subobjects, foreign_key: :parent_id
|
198
326
|
end
|
199
327
|
|
328
|
+
class SubobjectPrototype < MetalObject
|
329
|
+
amoeba do
|
330
|
+
enable
|
331
|
+
through :become_subobject
|
332
|
+
end
|
333
|
+
|
334
|
+
def become_subobject
|
335
|
+
self.dup.becomes Subobject
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
class Subobject < MetalObject
|
340
|
+
end
|
341
|
+
|
342
|
+
# Check of changing boolean attributes
|
343
|
+
|
344
|
+
class SuperAdmin < ::ActiveRecord::Base
|
345
|
+
amoeba do
|
346
|
+
set active: false
|
347
|
+
prepend password: false
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
# Proper inheritance
|
352
|
+
|
353
|
+
class Box < ActiveRecord::Base
|
354
|
+
has_many :products, class_name: 'BoxProduct'
|
355
|
+
has_many :sub_products, class_name: 'BoxSubProduct'
|
356
|
+
|
357
|
+
amoeba do
|
358
|
+
enable
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
class BoxProduct < ActiveRecord::Base
|
363
|
+
belongs_to :box, class_name: 'Box'
|
364
|
+
|
365
|
+
amoeba do
|
366
|
+
enable
|
367
|
+
propagate
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
class BoxSubProduct < BoxProduct
|
372
|
+
has_one :another_product, class_name: 'BoxAnotherProduct'
|
373
|
+
end
|
374
|
+
|
375
|
+
class BoxSubSubProduct < BoxSubProduct
|
376
|
+
end
|
377
|
+
|
378
|
+
class BoxAnotherProduct < BoxProduct
|
379
|
+
belongs_to :sub_product, class_name: 'BoxSubProduct'
|
380
|
+
end
|
381
|
+
|
382
|
+
# Inclusion inheritance
|
383
|
+
class Stage < ActiveRecord::Base
|
384
|
+
has_many :listeners
|
385
|
+
has_many :specialists
|
386
|
+
|
387
|
+
amoeba do
|
388
|
+
include_association :listeners
|
389
|
+
include_association :specialists
|
390
|
+
nullify :external_id
|
391
|
+
propagate
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
class Participant < ActiveRecord::Base
|
396
|
+
belongs_to :stage
|
397
|
+
end
|
398
|
+
|
399
|
+
class Listener < Participant
|
400
|
+
end
|
401
|
+
|
402
|
+
class Specialist < Participant
|
403
|
+
end
|
404
|
+
|
405
|
+
class CustomStage < Stage
|
406
|
+
has_many :custom_rules, foreign_key: :stage_id
|
407
|
+
|
408
|
+
amoeba do
|
409
|
+
include_association :custom_rules
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
class CustomRule < ActiveRecord::Base
|
414
|
+
belongs_to :custom_stage
|
415
|
+
end
|