activekit 0.1.3 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/active_kit/attribute.rb +8 -0
- data/lib/active_kit/activekitable.rb +1 -0
- data/lib/active_kit/activekiter.rb +11 -0
- data/lib/active_kit/engine.rb +0 -2
- data/lib/active_kit/loader.rb +23 -0
- data/lib/active_kit/relation.rb +7 -0
- data/lib/active_kit/sequence/sequence.rb +38 -0
- data/lib/active_kit/sequence/sequenceable.rb +27 -30
- data/lib/active_kit/sequence.rb +1 -1
- data/lib/active_kit/version.rb +1 -1
- data/lib/active_kit.rb +3 -0
- metadata +6 -3
- data/lib/active_kit/sequence/sequencer.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67eb8f62ef1b3e4f6532c5431730922130158646b4067ed14511314777d18448
|
4
|
+
data.tar.gz: 11d7429b7011c2aca230935789489c4ac6828ff60e4cb250fe18910fd14d2daf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63885175b26d2bace31dd3ded154ab4631819645f4c2cc41653e57179968f03149f2f352c399c9693bb69bbc476e322f3c7ef67e9e4f159e956111bc478fde7c
|
7
|
+
data.tar.gz: fdd159ca5f30a970452036b5d8fd8eb384466dc908c166b7873144a2cee0f3c6cd8b671b23813db22073b389dbb916469576c8eef3cd0a44d1ca80e844507372
|
@@ -5,5 +5,13 @@ module ActiveKit
|
|
5
5
|
store :value, accessors: [ :sequence ], coder: JSON
|
6
6
|
|
7
7
|
validates :value, presence: true, length: { maximum: 1073741823, allow_blank: true }
|
8
|
+
|
9
|
+
before_validation :set_defaults
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def set_defaults
|
14
|
+
self.sequence = { attributes: {} } if self.sequence.blank?
|
15
|
+
end
|
8
16
|
end
|
9
17
|
end
|
data/lib/active_kit/engine.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActiveKit
|
2
|
+
module Loader
|
3
|
+
def self.ensure_setup_for!(current_class:)
|
4
|
+
current_class.class_eval do
|
5
|
+
unless self.reflect_on_association :activekit_association
|
6
|
+
has_one :activekit_association, as: :record, dependent: :destroy, class_name: "ActiveKit::Attribute"
|
7
|
+
|
8
|
+
def activekit
|
9
|
+
@activekit ||= Relation.new(current_object: self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.activekiter
|
13
|
+
@activekiter ||= Activekiter.new(current_class: self)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.ensure_has_one_association_for!(record:)
|
20
|
+
record.create_activekit_association unless record.activekit_association
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ActiveKit
|
2
|
+
module Sequence
|
3
|
+
class Sequence
|
4
|
+
attr_reader :defined_attributes
|
5
|
+
|
6
|
+
def initialize(current_class:)
|
7
|
+
@current_class = current_class
|
8
|
+
|
9
|
+
@defined_attributes = {}
|
10
|
+
@wordbook = Wordbook.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def update(record:, attribute_name:, position:)
|
14
|
+
ActiveKit::Loader.ensure_has_one_association_for!(record: record)
|
15
|
+
|
16
|
+
if position
|
17
|
+
raise "position '#{position}' is not a valid unsigned integer value greater than 0." unless position.is_a?(Integer) && position > 0
|
18
|
+
|
19
|
+
wordbook = Wordbook.new
|
20
|
+
word_for_position = wordbook.next_word(count: position)
|
21
|
+
# TODO: committer record for the attribute with given word_for_position should be found and resaved to recalculate its position.
|
22
|
+
# json_where = 'value->"$.sequence.attributes.' + attribute_name.to_s + '" = "' + word_for_position + '"'
|
23
|
+
# record_at_position = ActiveKit::Attribute.where(record_type: record.class.name).where(json_where).first&.record
|
24
|
+
record.activekit_association.sequence[:attributes][attribute_name.to_sym] = word_for_position
|
25
|
+
record.activekit_association.save!
|
26
|
+
# record_at_position.save! if record_at_position
|
27
|
+
else
|
28
|
+
record.activekit_association.sequence[:attributes][attribute_name.to_sym] = nil
|
29
|
+
record.activekit_association.save!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_attribute(name:, options:)
|
34
|
+
@defined_attributes.store(name, options)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -17,31 +17,25 @@ module ActiveKit
|
|
17
17
|
# sequence_attribute :name, :positioning_method, updater: { via: :assoc, on: {} }
|
18
18
|
# sequence_attribute :name, :positioning_method, updater: { via: {}, on: {} }
|
19
19
|
# Note: :on and :via in :updater can accept nested associations.
|
20
|
-
def sequence_attribute(name, positioning_method, **options)
|
20
|
+
def sequence_attribute(name, positioning_method = nil, **options)
|
21
|
+
ActiveKit::Loader.ensure_setup_for!(current_class: self)
|
22
|
+
|
21
23
|
name = name.to_sym
|
22
|
-
positioning_method
|
24
|
+
options.store(:positioning_method, positioning_method&.to_sym)
|
23
25
|
options.deep_symbolize_keys!
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
@sequencer ||= ActiveKit::Sequence::Sequencer.new(current_class: self)
|
28
|
-
end
|
29
|
-
|
30
|
-
# scope :order_sequence, -> (options_hash) { includes(:sequence_attributes).where(sequence_attributes: { name: name.to_s }).order("sequence_attributes.value": :asc) }
|
31
|
-
end
|
32
|
-
|
33
|
-
set_active_sequence_callbacks(attribute_name: name, positioning_method: positioning_method, updater: options.delete(:updater))
|
34
|
-
|
35
|
-
sequencer.add_attribute(name: name, options: options)
|
27
|
+
set_active_sequence_callbacks(attribute_name: name, options: options)
|
28
|
+
activekiter.sequence.add_attribute(name: name, options: options)
|
36
29
|
end
|
37
30
|
|
38
|
-
def set_active_sequence_callbacks(attribute_name:,
|
39
|
-
|
31
|
+
def set_active_sequence_callbacks(attribute_name:, options:)
|
32
|
+
positioning_method = options.dig(:positioning_method)
|
33
|
+
updater = options.dig(:updater) || {}
|
40
34
|
|
41
35
|
if updater.empty?
|
42
|
-
|
36
|
+
after_save do
|
43
37
|
position = positioning_method ? self.public_send(positioning_method) : nil
|
44
|
-
self.class.
|
38
|
+
self.class.activekiter.sequence.update(record: self, attribute_name: attribute_name, position: position)
|
45
39
|
logger.info "ActiveSequence - Sequencing from #{self.class.name}: Done."
|
46
40
|
end
|
47
41
|
else
|
@@ -52,20 +46,23 @@ module ActiveKit
|
|
52
46
|
updater_via = updater.delete(:via)
|
53
47
|
updater_on = updater.delete(:on) || updater
|
54
48
|
|
55
|
-
base_klass = search_base_klass(self.
|
56
|
-
klass = reflected_klass(base_klass, updater_on.
|
49
|
+
base_klass = search_base_klass(self.name, updater_via)
|
50
|
+
klass = reflected_klass(base_klass, updater_on.keys.first)
|
57
51
|
klass.constantize.class_eval do
|
58
|
-
|
59
|
-
|
52
|
+
after_save :activekit_sequence_sequenceable_callback
|
53
|
+
after_destroy :activekit_sequence_sequenceable_callback
|
54
|
+
|
55
|
+
private def activekit_sequence_sequenceable_callback
|
56
|
+
inverse_assoc = self.class.search_inverse_assoc(self, updater_on)
|
60
57
|
position = positioning_method ? self.public_send(positioning_method) : nil
|
61
58
|
if inverse_assoc.respond_to?(:each)
|
62
|
-
inverse_assoc.each { |instance| instance.class.
|
59
|
+
inverse_assoc.each { |instance| instance.class.activekiter.sequence.update(record: instance, attribute_name: attribute_name, position: position) }
|
63
60
|
else
|
64
|
-
inverse_assoc.class.
|
61
|
+
inverse_assoc.class.activekiter.sequence.update(record: inverse_assoc, attribute_name: attribute_name, position: position)
|
65
62
|
end
|
66
63
|
logger.info "ActiveSequence - Sequencing from #{self.class.name}: Done."
|
67
64
|
end
|
68
|
-
end
|
65
|
+
end
|
69
66
|
end
|
70
67
|
end
|
71
68
|
|
@@ -75,8 +72,8 @@ module ActiveKit
|
|
75
72
|
elsif updater_via.is_a? Symbol
|
76
73
|
reflected_klass(classname, updater_via)
|
77
74
|
elsif updater_via.is_a? Hash
|
78
|
-
klass = reflected_klass(classname, updater_via.
|
79
|
-
updater_via.
|
75
|
+
klass = reflected_klass(classname, updater_via.keys.first)
|
76
|
+
updater_via.values.first.is_a?(Hash) ? search_base_klass(klass, updater_via.values.first) : reflected_klass(klass, updater_via.values.first)
|
80
77
|
end
|
81
78
|
end
|
82
79
|
|
@@ -87,11 +84,11 @@ module ActiveKit
|
|
87
84
|
end
|
88
85
|
|
89
86
|
def search_inverse_assoc(klass_object, updater_on)
|
90
|
-
if updater_on.
|
91
|
-
klass_object = klass_object.public_send(updater_on.
|
92
|
-
search_inverse_assoc(klass_object, updater_on.
|
87
|
+
if updater_on.values.first.is_a?(Hash)
|
88
|
+
klass_object = klass_object.public_send(updater_on.values.first.keys.first)
|
89
|
+
search_inverse_assoc(klass_object, updater_on.values.first)
|
93
90
|
else
|
94
|
-
klass_object.public_send(updater_on.
|
91
|
+
klass_object.public_send(updater_on.values.first)
|
95
92
|
end
|
96
93
|
end
|
97
94
|
end
|
data/lib/active_kit/sequence.rb
CHANGED
data/lib/active_kit/version.rb
CHANGED
data/lib/active_kit.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activekit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- plainsource
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -53,10 +53,13 @@ files:
|
|
53
53
|
- db/migrate/20231016050208_create_active_kit_attributes.rb
|
54
54
|
- lib/active_kit.rb
|
55
55
|
- lib/active_kit/activekitable.rb
|
56
|
+
- lib/active_kit/activekiter.rb
|
56
57
|
- lib/active_kit/engine.rb
|
58
|
+
- lib/active_kit/loader.rb
|
59
|
+
- lib/active_kit/relation.rb
|
57
60
|
- lib/active_kit/sequence.rb
|
61
|
+
- lib/active_kit/sequence/sequence.rb
|
58
62
|
- lib/active_kit/sequence/sequenceable.rb
|
59
|
-
- lib/active_kit/sequence/sequencer.rb
|
60
63
|
- lib/active_kit/sequence/wordbook.rb
|
61
64
|
- lib/active_kit/version.rb
|
62
65
|
- lib/activekit.rb
|
@@ -1,69 +0,0 @@
|
|
1
|
-
module ActiveKit
|
2
|
-
module Sequence
|
3
|
-
class Sequencer
|
4
|
-
attr_reader :defined_attributes
|
5
|
-
|
6
|
-
def initialize(current_class:)
|
7
|
-
@current_class = current_class
|
8
|
-
|
9
|
-
@defined_attributes = {}
|
10
|
-
@wordbook = Wordbook.new
|
11
|
-
end
|
12
|
-
|
13
|
-
def update(record:, attribute_name:, position:)
|
14
|
-
attribute = Attribute.find_by(record: record, name: attribute_name)
|
15
|
-
Attribute.create!(record: record, name: attribute_name) unless attribute
|
16
|
-
|
17
|
-
if position
|
18
|
-
raise "position '#{position}' is not a valid unsigned integer value greater than 0." unless position.is_a?(Integer) && position > 0
|
19
|
-
|
20
|
-
attribute_at_position = Attribute.where(record_type: record.class.name, name: attribute_name).order(value: :asc).offset(position - 1).limit(1)
|
21
|
-
attribute
|
22
|
-
|
23
|
-
wordbook = Wordbook.new
|
24
|
-
total_position_count = Attribute.where(record_type: record.class.name, name: attribute_name).order(value: :asc).count
|
25
|
-
if attribute == attribute_at_position(position)
|
26
|
-
return
|
27
|
-
elsif position == 1
|
28
|
-
|
29
|
-
elsif position == total_position_count
|
30
|
-
wordbook.bookmark = attribute_at_position(total_position_count).value
|
31
|
-
|
32
|
-
attribute.value = wordbook.next_word if wordbook.next_word?
|
33
|
-
attribute.save!
|
34
|
-
elsif position > total_position_count
|
35
|
-
maximum_word = Attribute.where(record_type: record.class.name, name: attribute_name).maximum(:value)
|
36
|
-
|
37
|
-
wordbook.bookmark = maximum_word
|
38
|
-
attribute.value = wordbook.next_word if wordbook.next_word?
|
39
|
-
attribute.save!
|
40
|
-
elsif position < total_position_count
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def rebalance_from(position:)
|
47
|
-
ActiveRecord::Base.transaction do
|
48
|
-
wordbook = Wordbook.new
|
49
|
-
Attribute.where(record_type: record.class.name, name: attribute_name).order(value: :asc).offset(position - 1).limit(1)
|
50
|
-
Attribute.where(record_type: record.class.name, name: attribute_name).order(value: :asc).offset(position - 1).each do |attribute|
|
51
|
-
wordbook.bookmark = attribute.value
|
52
|
-
raise "Could not find next word in wordbook while rebalancing" unless wordbook.next_word?
|
53
|
-
|
54
|
-
attribute.value = wordbook.next_word
|
55
|
-
attribute.save!
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def attribute_at_position(position)
|
61
|
-
Attribute.where(record_type: record.class.name, name: attribute_name).order(value: :asc).offset(position - 1).limit(1)
|
62
|
-
end
|
63
|
-
|
64
|
-
def add_attribute(name:, options:)
|
65
|
-
@defined_attributes.store(name, options)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|