closure_tree 6.4.0 → 7.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 +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +19 -12
- data/Appraisals +75 -7
- data/CHANGELOG.md +92 -39
- data/Gemfile +0 -12
- data/README.md +67 -24
- data/_config.yml +1 -0
- data/closure_tree.gemspec +10 -7
- data/lib/closure_tree/finders.rb +32 -9
- data/lib/closure_tree/has_closure_tree.rb +4 -0
- data/lib/closure_tree/has_closure_tree_root.rb +4 -6
- data/lib/closure_tree/hash_tree_support.rb +4 -4
- data/lib/closure_tree/hierarchy_maintenance.rb +31 -11
- data/lib/closure_tree/model.rb +42 -16
- data/lib/closure_tree/numeric_deterministic_ordering.rb +20 -6
- data/lib/closure_tree/numeric_order_support.rb +7 -3
- data/lib/closure_tree/support.rb +18 -12
- data/lib/closure_tree/support_attributes.rb +10 -1
- data/lib/closure_tree/support_flags.rb +1 -4
- data/lib/closure_tree/version.rb +1 -1
- data/lib/generators/closure_tree/migration_generator.rb +8 -0
- data/lib/generators/closure_tree/templates/create_hierarchies_table.rb.erb +1 -1
- metadata +29 -75
- data/gemfiles/activerecord_4.2.gemfile +0 -19
- data/gemfiles/activerecord_5.0.gemfile +0 -19
- data/gemfiles/activerecord_5.0_foreigner.gemfile +0 -20
- data/gemfiles/activerecord_edge.gemfile +0 -20
- data/img/example.png +0 -0
- data/img/preorder.png +0 -0
- data/spec/cache_invalidation_spec.rb +0 -39
- data/spec/cuisine_type_spec.rb +0 -38
- data/spec/db/database.yml +0 -21
- data/spec/db/models.rb +0 -128
- data/spec/db/schema.rb +0 -166
- data/spec/fixtures/tags.yml +0 -98
- data/spec/generators/migration_generator_spec.rb +0 -48
- data/spec/has_closure_tree_root_spec.rb +0 -154
- data/spec/hierarchy_maintenance_spec.rb +0 -16
- data/spec/label_spec.rb +0 -554
- data/spec/matcher_spec.rb +0 -34
- data/spec/metal_spec.rb +0 -55
- data/spec/model_spec.rb +0 -9
- data/spec/namespace_type_spec.rb +0 -13
- data/spec/parallel_spec.rb +0 -159
- data/spec/spec_helper.rb +0 -24
- data/spec/support/database.rb +0 -52
- data/spec/support/database_cleaner.rb +0 -14
- data/spec/support/exceed_query_limit.rb +0 -18
- data/spec/support/hash_monkey_patch.rb +0 -13
- data/spec/support/query_counter.rb +0 -18
- data/spec/support/sqlite3_with_advisory_lock.rb +0 -10
- data/spec/support_spec.rb +0 -14
- data/spec/tag_examples.rb +0 -665
- data/spec/tag_spec.rb +0 -6
- data/spec/user_spec.rb +0 -174
- data/spec/uuid_tag_spec.rb +0 -6
@@ -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
|
data/spec/cuisine_type_spec.rb
DELETED
@@ -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
|
data/spec/db/schema.rb
DELETED
@@ -1,166 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
ActiveRecord::Schema.define(:version => 0) do
|
4
|
-
|
5
|
-
create_table "tags" do |t|
|
6
|
-
t.string "name"
|
7
|
-
t.string "title"
|
8
|
-
t.integer "parent_id"
|
9
|
-
t.integer "sort_order"
|
10
|
-
t.timestamps null: false
|
11
|
-
end
|
12
|
-
|
13
|
-
add_foreign_key(:tags, :tags, :column => 'parent_id')
|
14
|
-
|
15
|
-
create_table "tag_hierarchies", :id => false do |t|
|
16
|
-
t.integer "ancestor_id", :null => false
|
17
|
-
t.integer "descendant_id", :null => false
|
18
|
-
t.integer "generations", :null => false
|
19
|
-
end
|
20
|
-
|
21
|
-
add_foreign_key(:tag_hierarchies, :tags, :column => 'ancestor_id')
|
22
|
-
add_foreign_key(:tag_hierarchies, :tags, :column => 'descendant_id')
|
23
|
-
|
24
|
-
create_table "uuid_tags", :id => false do |t|
|
25
|
-
t.string "uuid", :unique => true
|
26
|
-
t.string "name"
|
27
|
-
t.string "title"
|
28
|
-
t.string "parent_uuid"
|
29
|
-
t.integer "sort_order"
|
30
|
-
t.timestamps null: false
|
31
|
-
end
|
32
|
-
|
33
|
-
create_table "uuid_tag_hierarchies", :id => false do |t|
|
34
|
-
t.string "ancestor_id", :null => false
|
35
|
-
t.string "descendant_id", :null => false
|
36
|
-
t.integer "generations", :null => false
|
37
|
-
end
|
38
|
-
|
39
|
-
create_table "destroyed_tags" do |t|
|
40
|
-
t.string "name"
|
41
|
-
end
|
42
|
-
|
43
|
-
add_index "tag_hierarchies", [:ancestor_id, :descendant_id, :generations], :unique => true, :name => "tag_anc_desc_idx"
|
44
|
-
add_index "tag_hierarchies", [:descendant_id], :name => "tag_desc_idx"
|
45
|
-
|
46
|
-
create_table "groups" do |t|
|
47
|
-
t.string "name", null: false
|
48
|
-
end
|
49
|
-
|
50
|
-
create_table "groupings" do |t|
|
51
|
-
t.string "name", null: false
|
52
|
-
end
|
53
|
-
|
54
|
-
create_table "user_sets" do |t|
|
55
|
-
t.string "name", null: false
|
56
|
-
end
|
57
|
-
|
58
|
-
create_table "teams" do |t|
|
59
|
-
t.string "name", null: false
|
60
|
-
end
|
61
|
-
|
62
|
-
create_table "users" do |t|
|
63
|
-
t.string "email"
|
64
|
-
t.integer "referrer_id"
|
65
|
-
t.integer "group_id"
|
66
|
-
t.timestamps null: false
|
67
|
-
end
|
68
|
-
|
69
|
-
add_foreign_key(:users, :users, :column => 'referrer_id')
|
70
|
-
|
71
|
-
create_table "contracts" do |t|
|
72
|
-
t.integer "user_id", :null => false
|
73
|
-
t.integer "contract_type_id"
|
74
|
-
t.string "title"
|
75
|
-
end
|
76
|
-
|
77
|
-
create_table "contract_types" do |t|
|
78
|
-
t.string "name", :null => false
|
79
|
-
end
|
80
|
-
|
81
|
-
create_table "referral_hierarchies", :id => false do |t|
|
82
|
-
t.integer "ancestor_id", :null => false
|
83
|
-
t.integer "descendant_id", :null => false
|
84
|
-
t.integer "generations", :null => false
|
85
|
-
end
|
86
|
-
|
87
|
-
add_index "referral_hierarchies", [:ancestor_id, :descendant_id, :generations], :unique => true, :name => "ref_anc_desc_idx"
|
88
|
-
add_index "referral_hierarchies", [:descendant_id], :name => "ref_desc_idx"
|
89
|
-
|
90
|
-
create_table "labels" do |t|
|
91
|
-
t.string "name"
|
92
|
-
t.string "type"
|
93
|
-
t.integer "column_whereby_ordering_is_inferred"
|
94
|
-
t.integer "mother_id"
|
95
|
-
end
|
96
|
-
|
97
|
-
add_foreign_key(:labels, :labels, :column => 'mother_id')
|
98
|
-
|
99
|
-
create_table "label_hierarchies", :id => false do |t|
|
100
|
-
t.integer "ancestor_id", :null => false
|
101
|
-
t.integer "descendant_id", :null => false
|
102
|
-
t.integer "generations", :null => false
|
103
|
-
end
|
104
|
-
|
105
|
-
add_index "label_hierarchies", [:ancestor_id, :descendant_id, :generations], :unique => true, :name => "lh_anc_desc_idx"
|
106
|
-
add_index "label_hierarchies", [:descendant_id], :name => "lh_desc_idx"
|
107
|
-
|
108
|
-
create_table "cuisine_types" do |t|
|
109
|
-
t.string "name"
|
110
|
-
t.integer "parent_id"
|
111
|
-
end
|
112
|
-
|
113
|
-
create_table "cuisine_type_hierarchies", :id => false do |t|
|
114
|
-
t.integer "ancestor_id", :null => false
|
115
|
-
t.integer "descendant_id", :null => false
|
116
|
-
t.integer "generations", :null => false
|
117
|
-
end
|
118
|
-
|
119
|
-
create_table "namespace_types" do |t|
|
120
|
-
t.string "name"
|
121
|
-
t.integer "parent_id"
|
122
|
-
end
|
123
|
-
|
124
|
-
create_table "namespace_type_hierarchies", :id => false do |t|
|
125
|
-
t.integer "ancestor_id", :null => false
|
126
|
-
t.integer "descendant_id", :null => false
|
127
|
-
t.integer "generations", :null => false
|
128
|
-
end
|
129
|
-
|
130
|
-
create_table "metal" do |t|
|
131
|
-
t.integer "parent_id"
|
132
|
-
t.string "metal_type"
|
133
|
-
t.string "value"
|
134
|
-
t.string "description"
|
135
|
-
t.integer "sort_order"
|
136
|
-
end
|
137
|
-
|
138
|
-
add_foreign_key(:metal, :metal, :column => 'parent_id')
|
139
|
-
|
140
|
-
create_table "metal_hierarchies", :id => false do |t|
|
141
|
-
t.integer "ancestor_id", :null => false
|
142
|
-
t.integer "descendant_id", :null => false
|
143
|
-
t.integer "generations", :null => false
|
144
|
-
end
|
145
|
-
|
146
|
-
add_foreign_key(:metal_hierarchies, :metal, :column => 'ancestor_id')
|
147
|
-
add_foreign_key(:metal_hierarchies, :metal, :column => 'descendant_id')
|
148
|
-
|
149
|
-
create_table 'menu_items' do |t|
|
150
|
-
t.string 'name'
|
151
|
-
t.integer 'parent_id'
|
152
|
-
t.timestamps null: false
|
153
|
-
end
|
154
|
-
|
155
|
-
add_foreign_key(:menu_items, :menu_items, :column => 'parent_id')
|
156
|
-
|
157
|
-
create_table 'menu_item_hierarchies', :id => false do |t|
|
158
|
-
t.integer 'ancestor_id', :null => false
|
159
|
-
t.integer 'descendant_id', :null => false
|
160
|
-
t.integer 'generations', :null => false
|
161
|
-
end
|
162
|
-
|
163
|
-
add_foreign_key(:menu_item_hierarchies, :menu_items, :column => 'ancestor_id')
|
164
|
-
add_foreign_key(:menu_item_hierarchies, :menu_items, :column => 'descendant_id')
|
165
|
-
|
166
|
-
end
|