closure_tree 6.5.0 → 7.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +98 -0
  3. data/.gitignore +2 -0
  4. data/.rspec +1 -1
  5. data/Appraisals +90 -7
  6. data/CHANGELOG.md +100 -42
  7. data/Gemfile +3 -11
  8. data/README.md +68 -24
  9. data/Rakefile +16 -10
  10. data/_config.yml +1 -0
  11. data/bin/appraisal +29 -0
  12. data/bin/rake +29 -0
  13. data/bin/rspec +29 -0
  14. data/closure_tree.gemspec +16 -9
  15. data/lib/closure_tree/finders.rb +32 -9
  16. data/lib/closure_tree/has_closure_tree.rb +4 -0
  17. data/lib/closure_tree/has_closure_tree_root.rb +5 -7
  18. data/lib/closure_tree/hash_tree_support.rb +4 -4
  19. data/lib/closure_tree/hierarchy_maintenance.rb +28 -8
  20. data/lib/closure_tree/model.rb +42 -16
  21. data/lib/closure_tree/numeric_deterministic_ordering.rb +20 -6
  22. data/lib/closure_tree/numeric_order_support.rb +7 -3
  23. data/lib/closure_tree/support.rb +18 -12
  24. data/lib/closure_tree/support_attributes.rb +10 -1
  25. data/lib/closure_tree/support_flags.rb +1 -4
  26. data/lib/closure_tree/version.rb +1 -1
  27. data/lib/generators/closure_tree/migration_generator.rb +8 -0
  28. data/lib/generators/closure_tree/templates/create_hierarchies_table.rb.erb +1 -1
  29. metadata +78 -79
  30. data/.travis.yml +0 -29
  31. data/gemfiles/activerecord_4.2.gemfile +0 -19
  32. data/gemfiles/activerecord_5.0.gemfile +0 -19
  33. data/gemfiles/activerecord_5.0_foreigner.gemfile +0 -20
  34. data/gemfiles/activerecord_edge.gemfile +0 -20
  35. data/img/example.png +0 -0
  36. data/img/preorder.png +0 -0
  37. data/spec/cache_invalidation_spec.rb +0 -39
  38. data/spec/cuisine_type_spec.rb +0 -38
  39. data/spec/db/database.yml +0 -21
  40. data/spec/db/models.rb +0 -128
  41. data/spec/db/schema.rb +0 -166
  42. data/spec/fixtures/tags.yml +0 -98
  43. data/spec/generators/migration_generator_spec.rb +0 -48
  44. data/spec/has_closure_tree_root_spec.rb +0 -154
  45. data/spec/hierarchy_maintenance_spec.rb +0 -16
  46. data/spec/label_spec.rb +0 -554
  47. data/spec/matcher_spec.rb +0 -34
  48. data/spec/metal_spec.rb +0 -55
  49. data/spec/model_spec.rb +0 -9
  50. data/spec/namespace_type_spec.rb +0 -13
  51. data/spec/parallel_spec.rb +0 -159
  52. data/spec/spec_helper.rb +0 -24
  53. data/spec/support/database.rb +0 -52
  54. data/spec/support/database_cleaner.rb +0 -14
  55. data/spec/support/exceed_query_limit.rb +0 -18
  56. data/spec/support/hash_monkey_patch.rb +0 -13
  57. data/spec/support/query_counter.rb +0 -18
  58. data/spec/support/sqlite3_with_advisory_lock.rb +0 -10
  59. data/spec/support_spec.rb +0 -14
  60. data/spec/tag_examples.rb +0 -665
  61. data/spec/tag_spec.rb +0 -6
  62. data/spec/user_spec.rb +0 -174
  63. data/spec/uuid_tag_spec.rb +0 -6
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: closure_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.5.0
4
+ version: 7.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew McEachen
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-17 00:00:00.000000000 Z
11
+ date: 2021-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,30 +16,30 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.1.0
19
+ version: 4.2.10
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 4.1.0
26
+ version: 4.2.10
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: with_advisory_lock
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 3.0.0
33
+ version: 4.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 3.0.0
40
+ version: 4.0.0
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec-instafail
42
+ name: appraisal
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec-rails
56
+ name: database_cleaner
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: database_cleaner
70
+ name: generator_spec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: appraisal
84
+ name: parallel
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: timecop
98
+ name: pg
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,63 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: parallel
112
+ name: rspec-instafail
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec-rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: sqlite3
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: simplecov
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: timecop
113
169
  requirement: !ruby/object:Gem::Requirement
114
170
  requirements:
115
171
  - - ">="
@@ -129,9 +185,9 @@ executables: []
129
185
  extensions: []
130
186
  extra_rdoc_files: []
131
187
  files:
188
+ - ".github/workflows/ci.yml"
132
189
  - ".gitignore"
133
190
  - ".rspec"
134
- - ".travis.yml"
135
191
  - ".yardopts"
136
192
  - Appraisals
137
193
  - CHANGELOG.md
@@ -139,13 +195,11 @@ files:
139
195
  - MIT-LICENSE
140
196
  - README.md
141
197
  - Rakefile
198
+ - _config.yml
199
+ - bin/appraisal
200
+ - bin/rake
201
+ - bin/rspec
142
202
  - closure_tree.gemspec
143
- - gemfiles/activerecord_4.2.gemfile
144
- - gemfiles/activerecord_5.0.gemfile
145
- - gemfiles/activerecord_5.0_foreigner.gemfile
146
- - gemfiles/activerecord_edge.gemfile
147
- - img/example.png
148
- - img/preorder.png
149
203
  - lib/closure_tree.rb
150
204
  - lib/closure_tree/active_record_support.rb
151
205
  - lib/closure_tree/configuration.rb
@@ -170,39 +224,12 @@ files:
170
224
  - lib/generators/closure_tree/templates/config.rb
171
225
  - lib/generators/closure_tree/templates/create_hierarchies_table.rb.erb
172
226
  - mktree.rb
173
- - spec/cache_invalidation_spec.rb
174
- - spec/cuisine_type_spec.rb
175
- - spec/db/database.yml
176
- - spec/db/models.rb
177
- - spec/db/schema.rb
178
- - spec/fixtures/tags.yml
179
- - spec/generators/migration_generator_spec.rb
180
- - spec/has_closure_tree_root_spec.rb
181
- - spec/hierarchy_maintenance_spec.rb
182
- - spec/label_spec.rb
183
- - spec/matcher_spec.rb
184
- - spec/metal_spec.rb
185
- - spec/model_spec.rb
186
- - spec/namespace_type_spec.rb
187
- - spec/parallel_spec.rb
188
- - spec/spec_helper.rb
189
- - spec/support/database.rb
190
- - spec/support/database_cleaner.rb
191
- - spec/support/exceed_query_limit.rb
192
- - spec/support/hash_monkey_patch.rb
193
- - spec/support/query_counter.rb
194
- - spec/support/sqlite3_with_advisory_lock.rb
195
- - spec/support_spec.rb
196
- - spec/tag_examples.rb
197
- - spec/tag_spec.rb
198
- - spec/user_spec.rb
199
- - spec/uuid_tag_spec.rb
200
227
  - tests.sh
201
228
  homepage: http://mceachen.github.io/closure_tree/
202
229
  licenses:
203
230
  - MIT
204
231
  metadata: {}
205
- post_install_message:
232
+ post_install_message:
206
233
  rdoc_options: []
207
234
  require_paths:
208
235
  - lib
@@ -217,36 +244,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
244
  - !ruby/object:Gem::Version
218
245
  version: '0'
219
246
  requirements: []
220
- rubyforge_project:
221
- rubygems_version: 2.5.1
222
- signing_key:
247
+ rubygems_version: 3.0.3
248
+ signing_key:
223
249
  specification_version: 4
224
250
  summary: Easily and efficiently make your ActiveRecord model support hierarchies
225
- test_files:
226
- - spec/cache_invalidation_spec.rb
227
- - spec/cuisine_type_spec.rb
228
- - spec/db/database.yml
229
- - spec/db/models.rb
230
- - spec/db/schema.rb
231
- - spec/fixtures/tags.yml
232
- - spec/generators/migration_generator_spec.rb
233
- - spec/has_closure_tree_root_spec.rb
234
- - spec/hierarchy_maintenance_spec.rb
235
- - spec/label_spec.rb
236
- - spec/matcher_spec.rb
237
- - spec/metal_spec.rb
238
- - spec/model_spec.rb
239
- - spec/namespace_type_spec.rb
240
- - spec/parallel_spec.rb
241
- - spec/spec_helper.rb
242
- - spec/support/database.rb
243
- - spec/support/database_cleaner.rb
244
- - spec/support/exceed_query_limit.rb
245
- - spec/support/hash_monkey_patch.rb
246
- - spec/support/query_counter.rb
247
- - spec/support/sqlite3_with_advisory_lock.rb
248
- - spec/support_spec.rb
249
- - spec/tag_examples.rb
250
- - spec/tag_spec.rb
251
- - spec/user_spec.rb
252
- - spec/uuid_tag_spec.rb
251
+ test_files: []
data/.travis.yml DELETED
@@ -1,29 +0,0 @@
1
- cache: bundler
2
- sudo: false
3
- language: ruby
4
- rvm:
5
- - 2.4.0
6
- - 2.3.3
7
- - 2.2.6
8
- # these haven't been passing for a while:
9
- # - jruby-head
10
- # - rbx
11
-
12
- gemfile:
13
- - gemfiles/activerecord_4.2.gemfile
14
- - gemfiles/activerecord_5.0_foreigner.gemfile
15
- - gemfiles/activerecord_5.0.gemfile
16
- - gemfiles/activerecord_edge.gemfile
17
-
18
- env:
19
- - DB=sqlite
20
- - DB=mysql
21
- - DB=postgresql
22
-
23
- script: WITH_ADVISORY_LOCK_PREFIX=$TRAVIS_JOB_ID bundle exec rake --trace spec:all
24
-
25
- matrix:
26
- allow_failures:
27
- - gemfile: gemfiles/activerecord_edge.gemfile
28
- - rvm: jruby-head
29
- - rvm: rbx
@@ -1,19 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 4.2.0"
6
-
7
- platforms :ruby, :rbx do
8
- gem "mysql2"
9
- gem "pg"
10
- gem "sqlite3"
11
- end
12
-
13
- platforms :jruby do
14
- gem "activerecord-jdbcmysql-adapter"
15
- gem "activerecord-jdbcpostgresql-adapter"
16
- gem "activerecord-jdbcsqlite3-adapter"
17
- end
18
-
19
- gemspec :path => "../"
@@ -1,19 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 5.0.0"
6
-
7
- platforms :ruby, :rbx do
8
- gem "mysql2"
9
- gem "pg"
10
- gem "sqlite3"
11
- end
12
-
13
- platforms :jruby do
14
- gem "activerecord-jdbcmysql-adapter"
15
- gem "activerecord-jdbcpostgresql-adapter"
16
- gem "activerecord-jdbcsqlite3-adapter"
17
- end
18
-
19
- gemspec :path => "../"
@@ -1,20 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 5.0.0"
6
- gem "foreigner"
7
-
8
- platforms :ruby, :rbx do
9
- gem "mysql2"
10
- gem "pg"
11
- gem "sqlite3"
12
- end
13
-
14
- platforms :jruby do
15
- gem "activerecord-jdbcmysql-adapter"
16
- gem "activerecord-jdbcpostgresql-adapter"
17
- gem "activerecord-jdbcsqlite3-adapter"
18
- end
19
-
20
- gemspec :path => "../"
@@ -1,20 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", :github => "rails/rails"
6
- gem "arel", :github => "rails/arel"
7
-
8
- platforms :ruby, :rbx do
9
- gem "mysql2"
10
- gem "pg"
11
- gem "sqlite3"
12
- end
13
-
14
- platforms :jruby do
15
- gem "activerecord-jdbcmysql-adapter"
16
- gem "activerecord-jdbcpostgresql-adapter"
17
- gem "activerecord-jdbcsqlite3-adapter"
18
- end
19
-
20
- gemspec :path => "../"
data/img/example.png DELETED
Binary file
data/img/preorder.png DELETED
Binary file
@@ -1,39 +0,0 @@
1
- require 'spec_helper'
2
-
3
-
4
- describe 'cache invalidation', cache: true do
5
- before do
6
- Timecop.travel(10.seconds.ago) do
7
- #create a long tree with 2 branch
8
- @root = MenuItem.create(
9
- name: SecureRandom.hex(10)
10
- )
11
- 2.times do
12
- parent = @root
13
- 10.times do
14
- parent = parent.children.create(
15
- name: SecureRandom.hex(10)
16
- )
17
- end
18
- end
19
- @first_leaf = MenuItem.leaves.first
20
- @second_leaf = MenuItem.leaves.last
21
- end
22
- end
23
-
24
- describe 'touch option' do
25
- it 'should invalidate cache for all it ancestors' do
26
- old_time_stamp = @first_leaf.ancestors.pluck(:updated_at)
27
- @first_leaf.touch
28
- new_time_stamp = @first_leaf.ancestors.pluck(:updated_at)
29
- expect(old_time_stamp).to_not eq(new_time_stamp)
30
- end
31
-
32
- it 'should not invalidate cache for another branch' do
33
- old_time_stamp = @second_leaf.updated_at
34
- @first_leaf.touch
35
- new_time_stamp = @second_leaf.updated_at
36
- expect(old_time_stamp).to eq(new_time_stamp)
37
- end
38
- end
39
- end
@@ -1,38 +0,0 @@
1
- require 'spec_helper'
2
-
3
- def assert_lineage(e, m)
4
- expect(m.parent).to eq(e)
5
- expect(m.self_and_ancestors).to eq([m, e])
6
-
7
- # make sure reloading doesn't affect the self_and_ancestors:
8
- m.reload
9
- expect(m.self_and_ancestors).to eq([m, e])
10
- end
11
-
12
- describe CuisineType do
13
- it "finds self and parents when children << is used" do
14
- e = CuisineType.new(:name => "e")
15
- m = CuisineType.new(:name => "m")
16
- e.children << m
17
- e.save
18
- assert_lineage(e, m)
19
- end
20
-
21
- it "finds self and parents properly if the constructor is used" do
22
- e = CuisineType.create(:name => "e")
23
- m = CuisineType.create(:name => "m", :parent => e)
24
- assert_lineage(e, m)
25
- end
26
-
27
- it "sets the table_name of the hierarchy class properly" do
28
- expect(CuisineTypeHierarchy.table_name).to eq(ActiveRecord::Base.table_name_prefix + "cuisine_type_hierarchies" + ActiveRecord::Base.table_name_suffix)
29
- end
30
-
31
- it 'fixes self_and_ancestors properly on reparenting' do
32
- a = CuisineType.create! :name => 'a'
33
- b = CuisineType.create! :name => 'b'
34
- expect(b.self_and_ancestors.to_a).to eq([b])
35
- a.children << b
36
- expect(b.self_and_ancestors.to_a).to eq([b, a])
37
- end
38
- end
data/spec/db/database.yml DELETED
@@ -1,21 +0,0 @@
1
- common: &common
2
- database: <%= db_name %>
3
- host: localhost
4
- pool: 50
5
- timeout: 5000
6
- reaping_frequency: 1000
7
- min_messages: ERROR
8
-
9
- sqlite:
10
- <<: *common
11
- adapter: <%= "jdbc" if defined? JRUBY_VERSION %>sqlite3
12
-
13
- postgresql:
14
- <<: *common
15
- adapter: postgresql
16
- username: postgres
17
-
18
- mysql:
19
- <<: *common
20
- adapter: mysql2
21
- username: root
data/spec/db/models.rb DELETED
@@ -1,128 +0,0 @@
1
- class Tag < ActiveRecord::Base
2
- has_closure_tree :dependent => :destroy, :order => :name
3
- before_destroy :add_destroyed_tag
4
-
5
- def to_s
6
- name
7
- end
8
-
9
- def add_destroyed_tag
10
- # Proof for the tests that the destroy rather than the delete method was called:
11
- DestroyedTag.create(:name => name)
12
- end
13
- end
14
-
15
- class UUIDTag < ActiveRecord::Base
16
- self.primary_key = :uuid
17
- before_create :set_uuid
18
- has_closure_tree dependent: :destroy, order: 'name', parent_column_name: 'parent_uuid'
19
- before_destroy :add_destroyed_tag
20
-
21
- def set_uuid
22
- self.uuid = SecureRandom.uuid
23
- end
24
-
25
- def to_s
26
- name
27
- end
28
-
29
- def add_destroyed_tag
30
- # Proof for the tests that the destroy rather than the delete method was called:
31
- DestroyedTag.create(:name => name)
32
- end
33
- end
34
-
35
- class DestroyedTag < ActiveRecord::Base
36
- end
37
-
38
- class Group < ActiveRecord::Base
39
- has_closure_tree_root :root_user
40
- end
41
-
42
- class Grouping < ActiveRecord::Base
43
- has_closure_tree_root :root_person, class_name: "User", foreign_key: :group_id
44
- end
45
-
46
- class UserSet < ActiveRecord::Base
47
- has_closure_tree_root :root_user, class_name: "Useur"
48
- end
49
-
50
- class Team < ActiveRecord::Base
51
- has_closure_tree_root :root_user, class_name: "User", foreign_key: :grp_id
52
- end
53
-
54
- class User < ActiveRecord::Base
55
- acts_as_tree :parent_column_name => "referrer_id",
56
- :name_column => 'email',
57
- :hierarchy_class_name => 'ReferralHierarchy',
58
- :hierarchy_table_name => 'referral_hierarchies'
59
-
60
- has_many :contracts, inverse_of: :user
61
- belongs_to :group # Can't use and don't need inverse_of here when using has_closure_tree_root.
62
-
63
- def indirect_contracts
64
- Contract.where(:user_id => descendant_ids)
65
- end
66
-
67
- def to_s
68
- email
69
- end
70
- end
71
-
72
- class Contract < ActiveRecord::Base
73
- belongs_to :user, inverse_of: :contracts
74
- belongs_to :contract_type, inverse_of: :contracts
75
- end
76
-
77
- class ContractType < ActiveRecord::Base
78
- has_many :contracts, inverse_of: :contract_type
79
- end
80
-
81
- class Label < ActiveRecord::Base
82
- # make sure order doesn't matter
83
- acts_as_tree :order => :column_whereby_ordering_is_inferred, # <- symbol, and not "sort_order"
84
- :parent_column_name => "mother_id",
85
- :dependent => :destroy
86
-
87
- def to_s
88
- "#{self.class}: #{name}"
89
- end
90
- end
91
-
92
- class EventLabel < Label
93
- end
94
-
95
- class DateLabel < Label
96
- end
97
-
98
- class DirectoryLabel < Label
99
- end
100
-
101
- class CuisineType < ActiveRecord::Base
102
- acts_as_tree
103
- end
104
-
105
- module Namespace
106
- def self.table_name_prefix
107
- 'namespace_'
108
- end
109
- class Type < ActiveRecord::Base
110
- has_closure_tree dependent: :destroy
111
- end
112
- end
113
-
114
- class Metal < ActiveRecord::Base
115
- self.table_name = "#{table_name_prefix}metal#{table_name_suffix}"
116
- has_closure_tree order: 'sort_order', name_column: 'value'
117
- self.inheritance_column = 'metal_type'
118
- end
119
-
120
- class Adamantium < Metal
121
- end
122
-
123
- class Unobtanium < Metal
124
- end
125
-
126
- class MenuItem < ActiveRecord::Base
127
- has_closure_tree touch: true, with_advisory_lock: false
128
- end