unidom-category 1.6.6 → 2.0.1
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/README.md +45 -0
- data/app/controllers/unidom/category/application_controller.rb +8 -2
- data/app/helpers/unidom/category/application_helper.rb +7 -1
- data/app/jobs/unidom/category/application_job.rb +7 -1
- data/app/mailers/unidom/category/application_mailer.rb +9 -3
- data/app/models/unidom/category/application_record.rb +8 -2
- data/app/models/unidom/category/categorizing.rb +23 -11
- data/app/models/unidom/category/category.rb +19 -13
- data/app/models/unidom/category/category_rollup.rb +39 -27
- data/app/models/unidom/category/category_scheme.rb +14 -8
- data/app/models/unidom/category/concerns/as_ancestor_category.rb +23 -17
- data/app/models/unidom/category/concerns/as_categorized.rb +24 -18
- data/app/models/unidom/category/concerns/as_category.rb +23 -17
- data/app/models/unidom/category/concerns/as_descendant_category.rb +23 -17
- data/app/views/layouts/unidom/category/application.html.erb +1 -1
- data/db/migrate/20000301000000_create_unidom_category_schemes.rb +4 -4
- data/db/migrate/20000302000000_create_unidom_categories.rb +7 -6
- data/db/migrate/20000303000000_create_unidom_category_rollups.rb +10 -8
- data/db/migrate/20000304000000_create_unidom_categorizings.rb +7 -6
- data/lib/rspec/models/unidom/category/categorizing_shared_examples.rb +19 -0
- data/lib/rspec/models/unidom/category/category_rollup_spec.rb +5 -0
- data/lib/unidom/category/rspec_shared_examples.rb +1 -0
- data/lib/unidom/category/version.rb +1 -1
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f47f7dac9883328a8746f8f3f699eaaa7fdde0e4b5a7145e60cc2e146fd56483
|
4
|
+
data.tar.gz: e2e005009371483e95c018661e2117f863a2d54726c452d39f79923712fbe351
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e72b79a725ebcf6e5f343602fc053fdfc0919f9b5fd91541584ee2f9b2eb638556fbddaf4e0e6a00d15f6c34d0bd2076d7cab6752294bb150b6df19138bca3d6
|
7
|
+
data.tar.gz: 3601009f81beb1e289baec9f4549b588b3168cd8f84ca7d2871bab5df3dd4e366e3759e6c70d64ded6c0c3a14d5947fa206e86321f2682eb88dc69a7a1981caf
|
data/README.md
CHANGED
@@ -62,31 +62,42 @@ include Unidom::Category::Concerns::AsDescendantCategory
|
|
62
62
|
|
63
63
|
The As Category concern do the following tasks for the includer automatically:
|
64
64
|
1. Define the has_many :categorizings macro as: ``has_many :categorizings, class_name: 'Category::Categorizing'``
|
65
|
+
|
65
66
|
2. Define the #categorize! method as: ``categorize!(categorized, at: Time.now, primary: true)``
|
67
|
+
|
66
68
|
3. Define the #categorize? method as: ``categorize?(categorized, at: Time.now, primary: true)``
|
67
69
|
|
68
70
|
### As Categorized concern
|
69
71
|
|
70
72
|
The As Categorized concern do the following tasks for the includer automatically:
|
71
73
|
1. Define the has_many :categorizings macro as: ``has_many :categorizings, class_name: 'Unidom::Category::Categorizing', as: :categorized``
|
74
|
+
|
72
75
|
2. Define the has_many :categories macro as: ``has_many :categories, through: :categorizings, source: :category``
|
76
|
+
|
73
77
|
3. Define the #is_categorized! method as: ``is_categorized!(into: nil, at: Time.now, primary: true)``
|
78
|
+
|
74
79
|
4. Define the #is_categorized? method as: ``is_categorized?(into: nil, at: Time.now, primary: true)``
|
75
80
|
|
76
81
|
### As Ancestor Category concern
|
77
82
|
|
78
83
|
The As Ancestor Category concern do the following tasks for the includer automatically:
|
79
84
|
1. Define the has_many :descendant_category_rollups macro as: ``has_many :descendant_category_rollups, class_name: 'Unidom::Category::CategoryRollup', foreign_key: :ancestor_category_id, source: :ancestor_category``
|
85
|
+
|
80
86
|
2. Define the has_many :descendant_categories macro as: ``has_many :descendant_categories, class_name: 'Unidom::Category::Category', through: :descendant_category_rollups``
|
87
|
+
|
81
88
|
3. Define the #roll_up! method as: ``roll_up!(it, at: Time.now, primary: true)``
|
89
|
+
|
82
90
|
4. Define the #roll_up? method as: ``roll_up?(it, at: Time.now, primary: true)``
|
83
91
|
|
84
92
|
### As Descendant Category concern
|
85
93
|
|
86
94
|
The As Descendant Category concern do the following tasks for the includer automatically:
|
87
95
|
1. Define the has_many :ancestor_category_rollups macro as: ``has_many :ancestor_category_rollups, class_name: 'Unidom::Category::CategoryRollup', foreign_key: :descendant_category_id, source: :descendant_category``
|
96
|
+
|
88
97
|
2. Define the has_many :ancestor_categories macro as: ``has_many :ancestor_categories, class_name: 'Unidom::Category::Category', through: :ancestor_category_rollups``
|
98
|
+
|
89
99
|
3. Define the #is_rolled_up! as: ``is_rolled_up!(it, at: Time.now, primary: true)``
|
100
|
+
|
90
101
|
4. Define the #is_rolled_up? as: ``is_rolled_up?(it, at: Time.now, primary: true)``
|
91
102
|
|
92
103
|
|
@@ -109,6 +120,8 @@ end
|
|
109
120
|
|
110
121
|
## RSpec examples
|
111
122
|
|
123
|
+
### RSpec example manifest (run automatically)
|
124
|
+
|
112
125
|
```ruby
|
113
126
|
# spec/models/unidom_spec.rb
|
114
127
|
require 'unidom/category/models_rspec'
|
@@ -119,3 +132,35 @@ require 'unidom/category/types_rspec'
|
|
119
132
|
# spec/validators/unidom_spec.rb
|
120
133
|
require 'unidom/category/validators_rspec'
|
121
134
|
```
|
135
|
+
|
136
|
+
### RSpec shared examples (to be integrated)
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
# spec/support/unidom_rspec_shared_examples.rb
|
140
|
+
require 'unidom/category/rspec_shared_examples'
|
141
|
+
|
142
|
+
# spec/models/unidom/category/categorizing_spec.rb
|
143
|
+
describe Unidom::Category::Categorizing, type: :model do
|
144
|
+
|
145
|
+
before :each do
|
146
|
+
end
|
147
|
+
|
148
|
+
after :each do
|
149
|
+
end
|
150
|
+
|
151
|
+
context do
|
152
|
+
|
153
|
+
model_attributes = {}
|
154
|
+
|
155
|
+
categorized = Unidom::Product::Product.create! name: 'Model X', abbreviation: 'MX', packing_norm: 'car', measurement_unit: 'car', opened_at: Time.now
|
156
|
+
|
157
|
+
tesla = Unidom::Party::Company.create! name: 'Tesla'
|
158
|
+
scheme = Unidom::Category::CategoryScheme.create! owner: tesla, name: 'eCar'
|
159
|
+
category = Unidom::Category::Category.create! scheme: scheme, name: 'Battery-powered vehicles'
|
160
|
+
|
161
|
+
it_behaves_like 'Unidom::Category::Categorizing', model_attributes, categorized, category
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
```
|
@@ -1,6 +1,12 @@
|
|
1
1
|
##
|
2
2
|
# Application controller 是模块内所有控制器的基类。
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
module Unidom
|
5
|
+
module Category
|
6
|
+
|
7
|
+
class ApplicationController < ActionController::Base
|
8
|
+
protect_from_forgery with: :exception
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
6
12
|
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
##
|
2
2
|
# Application mailer 是模块内所有电子邮件发送类的基类。
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
module Unidom
|
5
|
+
module Category
|
6
|
+
|
7
|
+
class ApplicationMailer < ActionMailer::Base
|
8
|
+
default from: 'from@example.com'
|
9
|
+
layout 'mailer'
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
7
13
|
end
|
@@ -1,6 +1,12 @@
|
|
1
1
|
##
|
2
2
|
# Application record 是模块内所有模型的抽象基类。
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
module Unidom
|
5
|
+
module Category
|
6
|
+
|
7
|
+
class ApplicationRecord < ActiveRecord::Base
|
8
|
+
self.abstract_class = true
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
6
12
|
end
|
@@ -1,20 +1,32 @@
|
|
1
1
|
##
|
2
2
|
# Categorizing 是分类(category)和被分类项(categorized)之间的关联关系。
|
3
3
|
|
4
|
-
|
4
|
+
module Unidom
|
5
|
+
module Category
|
5
6
|
|
6
|
-
|
7
|
+
class Categorizing < ApplicationRecord
|
7
8
|
|
8
|
-
|
9
|
+
self.table_name = 'unidom_categorizings'
|
9
10
|
|
10
|
-
|
11
|
-
belongs_to :categorized, polymorphic: true
|
11
|
+
include Unidom::Common::Concerns::ModelExtension
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
belongs_to :category, class_name: 'Unidom::Category::Category'
|
14
|
+
belongs_to :categorized, polymorphic: true
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
scope :category_is, ->(category) { where category_id: to_id(category) }
|
17
|
+
scope :categorized_is, ->(categorized) { where categorized: categorized }
|
18
|
+
|
19
|
+
def self.categorize!(categorized, into: nil, at: Time.now)
|
20
|
+
|
21
|
+
assert_present! :categorized, categorized
|
22
|
+
assert_present! :into, into
|
23
|
+
assert_present! :at, at
|
24
|
+
|
25
|
+
categorized_is(categorized).category_is(into).valid_at.alive.first_or_create! elemental: true, opened_at: at
|
19
26
|
|
20
|
-
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end unless Unidom::Common::Neglection.namespace_neglected? 'Unidom::Category::Categorizing'
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -1,22 +1,28 @@
|
|
1
1
|
##
|
2
2
|
# Category 是分类。
|
3
3
|
|
4
|
-
|
4
|
+
module Unidom
|
5
|
+
module Category
|
5
6
|
|
6
|
-
|
7
|
+
class Category < ApplicationRecord
|
7
8
|
|
8
|
-
|
9
|
-
include Unidom::Category::Concerns::AsCategory
|
10
|
-
include Unidom::Category::Concerns::AsAncestorCategory
|
11
|
-
include Unidom::Category::Concerns::AsDescendantCategory
|
9
|
+
self.table_name = 'unidom_categories'
|
12
10
|
|
13
|
-
|
14
|
-
|
11
|
+
include Unidom::Common::Concerns::ModelExtension
|
12
|
+
include Unidom::Category::Concerns::AsCategory
|
13
|
+
include Unidom::Category::Concerns::AsAncestorCategory
|
14
|
+
include Unidom::Category::Concerns::AsDescendantCategory
|
15
15
|
|
16
|
-
|
16
|
+
validates :name, presence: true, length: { in: 2..self.columns_hash['name'].limit }
|
17
|
+
validates :abbreviation, allow_blank: true, length: { in: 2..self.columns_hash['abbreviation'].limit }
|
17
18
|
|
18
|
-
|
19
|
-
scope :code_length_is, ->(length) { where 'LENGTH(code) = :code_length', code_length: length }
|
20
|
-
scope :code_starting_with, ->(prefix) { where 'code LIKE :prefix_expression', prefix_expression: prefix+'%' }
|
19
|
+
belongs_to :scheme, class_name: 'Unidom::Category::CategoryScheme', foreign_key: :scheme_id
|
21
20
|
|
22
|
-
|
21
|
+
scope :scheme_is, ->(scheme) { where scheme_id: to_id(scheme) }
|
22
|
+
scope :code_length_is, ->(length) { where 'LENGTH(code) = :code_length', code_length: length }
|
23
|
+
scope :code_starting_with, ->(prefix) { where 'code LIKE :prefix_expression', prefix_expression: prefix+'%' }
|
24
|
+
|
25
|
+
end unless Unidom::Common::Neglection.namespace_neglected? 'Unidom::Category::Category'
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -1,39 +1,51 @@
|
|
1
1
|
##
|
2
2
|
# Category Rollup 是分类的层级关系。
|
3
3
|
|
4
|
-
|
4
|
+
module Unidom
|
5
|
+
module Category
|
5
6
|
|
6
|
-
|
7
|
+
class CategoryRollup < ApplicationRecord
|
7
8
|
|
8
|
-
|
9
|
+
self.table_name = 'unidom_category_rollups'
|
9
10
|
|
10
|
-
|
11
|
+
include Unidom::Common::Concerns::ModelExtension
|
11
12
|
|
12
|
-
|
13
|
-
belongs_to :descendant_category, class_name: 'Unidom::Category::Category'
|
13
|
+
validates :distance, presence: true, numericality: { integer_only: true, greater_than: 0 }
|
14
14
|
|
15
|
-
|
15
|
+
belongs_to :ancestor_category, class_name: 'Unidom::Category::Category'
|
16
|
+
belongs_to :descendant_category, class_name: 'Unidom::Category::Category'
|
16
17
|
|
17
|
-
|
18
|
-
scope :descendant_category_is, ->(category) { where descendant_category_id: to_id(category) }
|
18
|
+
scope :apart, ->(distance = 1) { where distance: distance }
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
ancestor_category = record.ancestor_category_id
|
23
|
-
ancestor_category_rollups_1 = self.class.descendant_category_is(record.ancestor_category_id).alive
|
24
|
-
ancestor_category_rollups_1.each do |ancestor_category_rollup|
|
25
|
-
self.class.apart(1+ancestor_category_rollup.distance).
|
26
|
-
ancestor_category_is(ancestor_category_rollup.ancestor_category_id).
|
27
|
-
descendant_category_is(record.descendant_category_id).
|
28
|
-
first_or_create! elemental: ancestor_category_rollup.elemental, from_date: ancestor_category_rollup.from_date
|
29
|
-
end
|
30
|
-
}
|
20
|
+
scope :ancestor_category_is, ->(category) { where ancestor_category_id: to_id(category) }
|
21
|
+
scope :descendant_category_is, ->(category) { where descendant_category_id: to_id(category) }
|
31
22
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
23
|
+
after_create ->(record) {
|
24
|
+
return unless 1==record.distance
|
25
|
+
ancestor_category = record.ancestor_category_id
|
26
|
+
ancestor_category_rollups_1 = self.class.descendant_category_is(record.ancestor_category_id).alive
|
27
|
+
ancestor_category_rollups_1.each do |ancestor_category_rollup|
|
28
|
+
self.class.apart(1+ancestor_category_rollup.distance).
|
29
|
+
ancestor_category_is(ancestor_category_rollup.ancestor_category_id).
|
30
|
+
descendant_category_is(record.descendant_category_id).
|
31
|
+
first_or_create! elemental: ancestor_category_rollup.elemental, from_date: ancestor_category_rollup.from_date
|
32
|
+
end
|
33
|
+
}
|
34
|
+
|
35
|
+
##
|
36
|
+
# 将 it 归为 into 的下级分类,时间是 at ,缺省为当前时间。如:
|
37
|
+
# Unidom::Category::CategoryRollup.roll_up! moto, into: vehicle
|
38
|
+
def self.roll_up!(it, into: nil, at: Time.now)
|
39
|
+
|
40
|
+
assert_present! :it, it
|
41
|
+
assert_present! :into, into
|
42
|
+
assert_present! :at, at
|
43
|
+
|
44
|
+
self.descendant_category_is(it).ancestor_category_is(into).valid_at(now: at).alive.first_or_create! opened_at: at
|
38
45
|
|
39
|
-
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end unless Unidom::Common::Neglection.namespace_neglected? 'Unidom::Category::CategoryRollup'
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -2,17 +2,23 @@
|
|
2
2
|
# Category Scheme 是分类体系。
|
3
3
|
# 所有者(owner)可以是系统(System)、标准(Standard)、或者某个参与者(Party,如:Person、Shop、Company)。
|
4
4
|
|
5
|
-
|
5
|
+
module Unidom
|
6
|
+
module Category
|
6
7
|
|
7
|
-
|
8
|
+
class CategoryScheme < ApplicationRecord
|
8
9
|
|
9
|
-
|
10
|
+
self.table_name = 'unidom_category_schemes'
|
10
11
|
|
11
|
-
|
12
|
-
has_many :categories, class_name: 'Unidom::Category::Category', foreign_key: :scheme_id
|
12
|
+
include Unidom::Common::Concerns::ModelExtension
|
13
13
|
|
14
|
-
|
14
|
+
belongs_to :owner, polymorphic: true
|
15
|
+
has_many :categories, class_name: 'Unidom::Category::Category', foreign_key: :scheme_id
|
15
16
|
|
16
|
-
|
17
|
+
validates :name, presence: true, length: { in: 2..self.columns_hash['name'].limit }
|
17
18
|
|
18
|
-
|
19
|
+
scope :owned_by, ->(owner) { where owner: owner }
|
20
|
+
|
21
|
+
end unless Unidom::Common::Neglection.namespace_neglected? 'Unidom::Category::CategoryScheme'
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -1,26 +1,32 @@
|
|
1
|
-
module Unidom
|
1
|
+
module Unidom
|
2
|
+
module Category
|
3
|
+
module Concerns
|
4
|
+
module AsAncestorCategory
|
2
5
|
|
3
|
-
|
6
|
+
extend ActiveSupport::Concern
|
4
7
|
|
5
|
-
|
8
|
+
included do |includer|
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
has_many :descendant_category_rollups, class_name: 'Unidom::Category::CategoryRollup', foreign_key: :ancestor_category_id, source: :ancestor_category
|
11
|
+
has_many :descendant_categories, class_name: 'Unidom::Category::Category', through: :descendant_category_rollups
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def roll_up!(it, at: Time.now, primary: true)
|
14
|
+
rollup = descendant_category_rollups.descendant_category_is(it).valid_at(now: at).alive.first_or_create! elemental: primary, opened_at: at
|
15
|
+
rollup.elemental = primary if rollup.elemental!=primary
|
16
|
+
rollup.save!
|
17
|
+
rollup
|
18
|
+
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
def roll_up?(it, at: Time.now, primary: true)
|
21
|
+
descendant_category_rollups.descendant_category_is(it).primary(primary).valid_at(now: at).alive.exists?
|
22
|
+
end
|
20
23
|
|
21
|
-
|
24
|
+
end
|
22
25
|
|
23
|
-
|
24
|
-
|
26
|
+
module ClassMethods
|
27
|
+
end
|
25
28
|
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
26
32
|
end
|
@@ -1,33 +1,39 @@
|
|
1
|
-
module Unidom
|
1
|
+
module Unidom
|
2
|
+
module Category
|
3
|
+
module Concerns
|
4
|
+
module AsCategorized
|
2
5
|
|
3
|
-
|
6
|
+
extend ActiveSupport::Concern
|
4
7
|
|
5
|
-
|
8
|
+
included do |includer|
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
has_many :categorizings, class_name: 'Unidom::Category::Categorizing', as: :categorized
|
11
|
+
has_many :categories, through: :categorizings, source: :category
|
9
12
|
|
10
|
-
|
13
|
+
def is_categorized!(into: nil, at: Time.now, primary: true)
|
11
14
|
|
12
|
-
|
13
|
-
|
15
|
+
raise ArgumentError('The into argument is required.') if into.blank?
|
16
|
+
raise ArgumentError('The at argument is required.' ) if at.blank?
|
14
17
|
|
15
|
-
|
18
|
+
categorizings.category_is(into).valid_at(now: at).alive.first_or_create! elemental: primary, opened_at: at
|
16
19
|
|
17
|
-
|
20
|
+
end
|
18
21
|
|
19
|
-
|
22
|
+
def is_categorized?(into: nil, at: Time.now, primary: true)
|
20
23
|
|
21
|
-
|
22
|
-
|
24
|
+
raise ArgumentError('The into argument is required.') if into.blank?
|
25
|
+
raise ArgumentError('The at argument is required.' ) if at.blank?
|
23
26
|
|
24
|
-
|
27
|
+
categorizings.category_is(into).valid_at(now: at).alive.primary(primary).exists?
|
25
28
|
|
26
|
-
|
29
|
+
end
|
27
30
|
|
28
|
-
|
31
|
+
end
|
29
32
|
|
30
|
-
|
31
|
-
|
33
|
+
module ClassMethods
|
34
|
+
end
|
32
35
|
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
33
39
|
end
|
@@ -1,32 +1,38 @@
|
|
1
|
-
module Unidom
|
1
|
+
module Unidom
|
2
|
+
module Category
|
3
|
+
module Concerns
|
4
|
+
module AsCategory
|
2
5
|
|
3
|
-
|
6
|
+
extend ActiveSupport::Concern
|
4
7
|
|
5
|
-
|
8
|
+
included do |includer|
|
6
9
|
|
7
|
-
|
10
|
+
has_many :categorizings, class_name: 'Category::Categorizing'
|
8
11
|
|
9
|
-
|
12
|
+
def categorize!(categorized, at: Time.now, primary: true)
|
10
13
|
|
11
|
-
|
12
|
-
|
14
|
+
raise ArgumentError('The categorized argument is required.') if categorized.blank?
|
15
|
+
raise ArgumentError('The at argument is required.' ) if at.blank?
|
13
16
|
|
14
|
-
|
17
|
+
categorizings.categorized_is(categorized).valid_at(now: at).alive.first_or_create! elemental: primary, opened_at: at
|
15
18
|
|
16
|
-
|
19
|
+
end
|
17
20
|
|
18
|
-
|
21
|
+
def categorize?(categorized, at: Time.now, primary: true)
|
19
22
|
|
20
|
-
|
21
|
-
|
23
|
+
raise ArgumentError('The categorized argument is required.') if categorized.blank?
|
24
|
+
raise ArgumentError('The at argument is required.' ) if at.blank?
|
22
25
|
|
23
|
-
|
26
|
+
categorizings.categorized_is(categorized).valid_at(now: at).alive.primary(primary).exists?
|
24
27
|
|
25
|
-
|
28
|
+
end
|
26
29
|
|
27
|
-
|
30
|
+
end
|
28
31
|
|
29
|
-
|
30
|
-
|
32
|
+
module ClassMethods
|
33
|
+
end
|
31
34
|
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
32
38
|
end
|
@@ -1,26 +1,32 @@
|
|
1
|
-
module Unidom
|
1
|
+
module Unidom
|
2
|
+
module Category
|
3
|
+
module Concerns
|
4
|
+
module AsDescendantCategory
|
2
5
|
|
3
|
-
|
6
|
+
extend ActiveSupport::Concern
|
4
7
|
|
5
|
-
|
8
|
+
included do |includer|
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
has_many :ancestor_category_rollups, class_name: 'Unidom::Category::CategoryRollup', foreign_key: :descendant_category_id, source: :descendant_category
|
11
|
+
has_many :ancestor_categories, class_name: 'Unidom::Category::Category', through: :ancestor_category_rollups
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def is_rolled_up!(it, at: Time.now, primary: true)
|
14
|
+
rollup = ancestor_category_rollups.ancestor_category_is(it).valid_at(now: at).alive.first_or_create! elemental: primary, opened_at: at
|
15
|
+
rollup.elemental = primary if rollup.elemental!=primary
|
16
|
+
rollup.save!
|
17
|
+
rollup
|
18
|
+
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
def is_rolled_up?(it, at: Time.now, primary: true)
|
21
|
+
ancestor_category_rollups.ancestor_category_is(it).primary(primary).valid_at(now: at).alive.exists?
|
22
|
+
end
|
20
23
|
|
21
|
-
|
24
|
+
end
|
22
25
|
|
23
|
-
|
24
|
-
|
26
|
+
module ClassMethods
|
27
|
+
end
|
25
28
|
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
26
32
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class CreateUnidomCategorySchemes < ActiveRecord::Migration
|
1
|
+
class CreateUnidomCategorySchemes < ActiveRecord::Migration[6.0]
|
2
2
|
|
3
3
|
def change
|
4
4
|
|
@@ -12,9 +12,9 @@ class CreateUnidomCategorySchemes < ActiveRecord::Migration
|
|
12
12
|
|
13
13
|
t.text :description
|
14
14
|
|
15
|
-
t.column :state, 'char(1)', null: false, default:
|
16
|
-
t.datetime :opened_at, null: false, default: ::
|
17
|
-
t.datetime :closed_at, null: false, default: ::
|
15
|
+
t.column :state, 'char(1)', null: false, default: Unidom::Common::STATE
|
16
|
+
t.datetime :opened_at, null: false, default: Unidom::Common::OPENED_AT
|
17
|
+
t.datetime :closed_at, null: false, default: Unidom::Common::CLOSED_AT
|
18
18
|
t.boolean :defunct, null: false, default: false
|
19
19
|
t.jsonb :notation, null: false, default: {}
|
20
20
|
|
@@ -1,10 +1,11 @@
|
|
1
|
-
class CreateUnidomCategories < ActiveRecord::Migration
|
1
|
+
class CreateUnidomCategories < ActiveRecord::Migration[6.0]
|
2
2
|
|
3
3
|
def change
|
4
4
|
|
5
5
|
create_table :unidom_categories, id: :uuid do |t|
|
6
6
|
|
7
|
-
t.references :scheme, type: :uuid, null: false
|
7
|
+
t.references :scheme, type: :uuid, null: false,
|
8
|
+
foreign_key: false
|
8
9
|
|
9
10
|
t.string :code, null: true, default: nil, limit: 64
|
10
11
|
t.string :name, null: false, default: '', limit: 200
|
@@ -12,9 +13,9 @@ class CreateUnidomCategories < ActiveRecord::Migration
|
|
12
13
|
|
13
14
|
t.text :description
|
14
15
|
|
15
|
-
t.column :state, 'char(1)', null: false, default:
|
16
|
-
t.datetime :opened_at, null: false, default: ::
|
17
|
-
t.datetime :closed_at, null: false, default: ::
|
16
|
+
t.column :state, 'char(1)', null: false, default: Unidom::Common::STATE
|
17
|
+
t.datetime :opened_at, null: false, default: Unidom::Common::OPENED_AT
|
18
|
+
t.datetime :closed_at, null: false, default: Unidom::Common::CLOSED_AT
|
18
19
|
t.boolean :defunct, null: false, default: false
|
19
20
|
t.jsonb :notation, null: false, default: {}
|
20
21
|
|
@@ -22,7 +23,7 @@ class CreateUnidomCategories < ActiveRecord::Migration
|
|
22
23
|
|
23
24
|
end
|
24
25
|
|
25
|
-
add_index :unidom_categories, :scheme_id
|
26
|
+
#add_index :unidom_categories, :scheme_id
|
26
27
|
add_index :unidom_categories, [ :code, :scheme_id ], unique: true
|
27
28
|
|
28
29
|
end
|
@@ -1,18 +1,20 @@
|
|
1
|
-
class CreateUnidomCategoryRollups < ActiveRecord::Migration
|
1
|
+
class CreateUnidomCategoryRollups < ActiveRecord::Migration[6.0]
|
2
2
|
|
3
3
|
def change
|
4
4
|
|
5
5
|
create_table :unidom_category_rollups, id: :uuid do |t|
|
6
6
|
|
7
|
-
t.references :ancestor_category, type: :uuid, null: false
|
8
|
-
|
7
|
+
t.references :ancestor_category, type: :uuid, null: false,
|
8
|
+
foreign_key: false
|
9
|
+
t.references :descendant_category, type: :uuid, null: false,
|
10
|
+
foreign_key: false
|
9
11
|
|
10
12
|
t.boolean :elemental, null: false, default: false
|
11
13
|
t.integer :distance, null: false, default: 1
|
12
14
|
|
13
|
-
t.column :state, 'char(1)', null: false, default:
|
14
|
-
t.datetime :opened_at, null: false, default: ::
|
15
|
-
t.datetime :closed_at, null: false, default: ::
|
15
|
+
t.column :state, 'char(1)', null: false, default: Unidom::Common::STATE
|
16
|
+
t.datetime :opened_at, null: false, default: Unidom::Common::OPENED_AT
|
17
|
+
t.datetime :closed_at, null: false, default: Unidom::Common::CLOSED_AT
|
16
18
|
t.boolean :defunct, null: false, default: false
|
17
19
|
t.jsonb :notation, null: false, default: {}
|
18
20
|
|
@@ -20,8 +22,8 @@ class CreateUnidomCategoryRollups < ActiveRecord::Migration
|
|
20
22
|
|
21
23
|
end
|
22
24
|
|
23
|
-
add_index :unidom_category_rollups, :ancestor_category_id
|
24
|
-
add_index :unidom_category_rollups, :descendant_category_id
|
25
|
+
#add_index :unidom_category_rollups, :ancestor_category_id
|
26
|
+
#add_index :unidom_category_rollups, :descendant_category_id
|
25
27
|
|
26
28
|
end
|
27
29
|
|
@@ -1,18 +1,19 @@
|
|
1
|
-
class CreateUnidomCategorizings < ActiveRecord::Migration
|
1
|
+
class CreateUnidomCategorizings < ActiveRecord::Migration[6.0]
|
2
2
|
|
3
3
|
def change
|
4
4
|
|
5
5
|
create_table :unidom_categorizings, id: :uuid do |t|
|
6
6
|
|
7
|
-
t.references :category, type: :uuid, null: false
|
7
|
+
t.references :category, type: :uuid, null: false,
|
8
|
+
foreign_key: false
|
8
9
|
t.references :categorized, type: :uuid, null: false,
|
9
10
|
polymorphic: { type: :uuid, null: false }
|
10
11
|
|
11
12
|
t.boolean :elemental, null: false, default: false
|
12
13
|
|
13
|
-
t.column :state, 'char(1)', null: false, default:
|
14
|
-
t.datetime :opened_at, null: false, default: ::
|
15
|
-
t.datetime :closed_at, null: false, default: ::
|
14
|
+
t.column :state, 'char(1)', null: false, default: Unidom::Common::STATE
|
15
|
+
t.datetime :opened_at, null: false, default: Unidom::Common::OPENED_AT
|
16
|
+
t.datetime :closed_at, null: false, default: Unidom::Common::CLOSED_AT
|
16
17
|
t.boolean :defunct, null: false, default: false
|
17
18
|
t.jsonb :notation, null: false, default: {}
|
18
19
|
|
@@ -20,7 +21,7 @@ class CreateUnidomCategorizings < ActiveRecord::Migration
|
|
20
21
|
|
21
22
|
end
|
22
23
|
|
23
|
-
add_index :unidom_categorizings, :category_id
|
24
|
+
#add_index :unidom_categorizings, :category_id
|
24
25
|
add_index :unidom_categorizings, :categorized_id
|
25
26
|
|
26
27
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
shared_examples 'Unidom::Category::Categorizing' do |model_attributes, categorized, category|
|
2
|
+
|
3
|
+
before :each do
|
4
|
+
end
|
5
|
+
|
6
|
+
after :each do
|
7
|
+
end
|
8
|
+
|
9
|
+
context do
|
10
|
+
|
11
|
+
it_behaves_like 'assert_present!', described_class, :categorize!, [ categorized, { into: category, at: Time.now } ], [ { 0 => :categorized }, :into, :at ]
|
12
|
+
|
13
|
+
it_behaves_like 'has_many', model_attributes, :categorized, categorized.class, [ categorized.attributes ]
|
14
|
+
|
15
|
+
it_behaves_like 'monomorphic scope', model_attributes, :category_is, :category, [ category.class ]
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -28,6 +28,11 @@ describe Unidom::Category::CategoryRollup, type: :model do
|
|
28
28
|
it_behaves_like 'monomorphic scope', model_attributes, :ancestor_category_is, :ancestor_category
|
29
29
|
it_behaves_like 'monomorphic scope', model_attributes, :descendant_category_is, :descendant_category
|
30
30
|
|
31
|
+
it = Unidom::Category::Category.create! category_attributes.merge(code: 'ZC', name: 'Sub Category', abbreviation: 'SubCat')
|
32
|
+
into = Unidom::Category::Category.create! category_attributes.merge(code: 'YC')
|
33
|
+
|
34
|
+
it_behaves_like 'assert_present!', described_class, :roll_up!, [ it, { into: into, at: Time.now } ], [ { 0 => :it }, :into, :at ]
|
35
|
+
|
31
36
|
end
|
32
37
|
|
33
38
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rspec/models/unidom/category/categorizing_shared_examples'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unidom-category
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Topbit Du
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: unidom-common
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
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: '
|
26
|
+
version: '2.0'
|
27
27
|
description: Unidom (UNIfied Domain Object Model) is a series of domain model engines.
|
28
28
|
The Category domain model engine includes Category and its relative models. Unidom
|
29
29
|
(统一领域对象模型)是一系列的领域模型引擎。类别领域模型引擎包括类别及其相关的模型。
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- db/migrate/20000302000000_create_unidom_categories.rb
|
59
59
|
- db/migrate/20000303000000_create_unidom_category_rollups.rb
|
60
60
|
- db/migrate/20000304000000_create_unidom_categorizings.rb
|
61
|
+
- lib/rspec/models/unidom/category/categorizing_shared_examples.rb
|
61
62
|
- lib/rspec/models/unidom/category/categorizing_spec.rb
|
62
63
|
- lib/rspec/models/unidom/category/category_rollup_spec.rb
|
63
64
|
- lib/rspec/models/unidom/category/category_scheme_spec.rb
|
@@ -66,14 +67,15 @@ files:
|
|
66
67
|
- lib/unidom/category.rb
|
67
68
|
- lib/unidom/category/engine.rb
|
68
69
|
- lib/unidom/category/models_rspec.rb
|
70
|
+
- lib/unidom/category/rspec_shared_examples.rb
|
69
71
|
- lib/unidom/category/types_rspec.rb
|
70
72
|
- lib/unidom/category/validators_rspec.rb
|
71
73
|
- lib/unidom/category/version.rb
|
72
|
-
homepage: https://
|
74
|
+
homepage: https://gitee.com/Unidom/unidom-category
|
73
75
|
licenses:
|
74
76
|
- MIT
|
75
77
|
metadata: {}
|
76
|
-
post_install_message:
|
78
|
+
post_install_message:
|
77
79
|
rdoc_options: []
|
78
80
|
require_paths:
|
79
81
|
- lib
|
@@ -88,9 +90,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
90
|
- !ruby/object:Gem::Version
|
89
91
|
version: '0'
|
90
92
|
requirements: []
|
91
|
-
|
92
|
-
|
93
|
-
signing_key:
|
93
|
+
rubygems_version: 3.2.3
|
94
|
+
signing_key:
|
94
95
|
specification_version: 4
|
95
96
|
summary: Unidom Category Domain Model Engine 类别领域模型引擎
|
96
97
|
test_files: []
|