activekit 0.1.3 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf28e084bf1e87d21b36b3abcce5f3ebc902595a9635396f985c3935467e6b48
4
- data.tar.gz: ee2abf2cd217e523b35aa980dfa84072dee883dde5a2a782f864453740448321
3
+ metadata.gz: 98f08d0d1d37f5f2e3968da22af8cb3feb20704f5f5f6c6cf02d838fd2560354
4
+ data.tar.gz: ee3805f8d06d399c9519d0ae0360ee07f1069400033638eea6c2f9cfce519aac
5
5
  SHA512:
6
- metadata.gz: f9848ed64694d379141ab41865234ac80f6042452be9a3a34ee2f94db61fa7a9c4e3bd564fb85c6029bd7e86379e773fc5b3945a7676ea4955489cd325a72bd4
7
- data.tar.gz: 8724f2eb4848df56dd589ad04e241c8a95a47d27b80e2d3c7bc1838f4b02a76e726115c27c03f449699c40ca34c8f50667254b1056408dea42bf02e5aafa5bc0
6
+ metadata.gz: 6dc11428da73f1875bec2250f402df9e67053903b5b6c1762190fcf72f3c16d8f76f42c34bfcd34d9b9b5ecdf534d8d71d6bafbcd059dfe1c968652bfc8490f2
7
+ data.tar.gz: 73521d96b3200bbeaae1edda274ed4eff23154b66c8206b888b3ce540eb55d92a351925c628e4e4bcbbcfe3f007a23a945e12fbda6581c233d199b7a26150cae
@@ -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
@@ -4,6 +4,7 @@ require "active_kit/sequence/sequenceable"
4
4
  module ActiveKit
5
5
  module Activekitable
6
6
  extend ActiveSupport::Concern
7
+ include ActiveKit::Loader
7
8
  include ActiveKit::Sequence::Sequenceable
8
9
 
9
10
  included do
@@ -0,0 +1,11 @@
1
+ module ActiveKit
2
+ class Activekiter
3
+ def initialize(current_class:)
4
+ @current_class = current_class
5
+ end
6
+
7
+ def sequence
8
+ @sequence ||= ActiveKit::Sequence::Sequence.new(current_class: @current_class)
9
+ end
10
+ end
11
+ end
@@ -8,8 +8,6 @@ module ActiveKit
8
8
 
9
9
  ActiveSupport.on_load(:active_record) do
10
10
  include ActiveKit::Activekitable
11
-
12
- has_one :activekit, as: :record, dependent: :destroy, class_name: "ActiveKit::Attribute"
13
11
  end
14
12
  end
15
13
  end
@@ -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,7 @@
1
+ module ActiveKit
2
+ class Relation
3
+ def initialize(current_object:)
4
+ @current_object = current_object
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,37 @@
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
+ json_where = 'value->"$.sequence.attributes.' + attribute_name.to_s + '" = "' + word_for_position + '"'
22
+ record_at_position = ActiveKit::Attribute.where(record_type: record.class.name).where(json_where).first&.record
23
+ record.activekit_association.sequence[:attributes][attribute_name.to_sym] = word_for_position
24
+ record.activekit_association.save!
25
+ record_at_position.save! if record_at_position
26
+ else
27
+ record.activekit_association.sequence[:attributes][attribute_name.to_sym] = nil
28
+ record.activekit_association.save!
29
+ end
30
+ end
31
+
32
+ def add_attribute(name:, options:)
33
+ @defined_attributes.store(name, options)
34
+ end
35
+ end
36
+ end
37
+ 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 = positioning_method.to_sym
24
+ options.store(:positioning_method, positioning_method&.to_sym)
23
25
  options.deep_symbolize_keys!
24
26
 
25
- unless self.respond_to?(:sequencer)
26
- define_singleton_method :sequencer do
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:, positioning_method:, updater:)
39
- updater = updater || {}
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_commit do
43
37
  position = positioning_method ? self.public_send(positioning_method) : nil
44
- self.class.sequencer.update(record: self, attribute_name: attribute_name, position: position)
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,20 @@ 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.class.name, updater_via)
56
- klass = reflected_klass(base_klass, updater_on.key)
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
52
  after_commit do
59
- inverse_assoc = search_inverse_assoc(self, updater_on)
53
+ inverse_assoc = self.class.search_inverse_assoc(self, updater_on)
60
54
  position = positioning_method ? self.public_send(positioning_method) : nil
61
55
  if inverse_assoc.respond_to?(:each)
62
- inverse_assoc.each { |instance| instance.class.sequencer.update(record: instance, attribute_name: attribute_name, position: position) }
56
+ inverse_assoc.each { |instance| instance.class.activekiter.sequence.update(record: instance, attribute_name: attribute_name, position: position) }
63
57
  else
64
- inverse_assoc.class.sequencer.update(record: inverse_assoc, attribute_name: attribute_name, position: position)
58
+ inverse_assoc.class.activekiter.sequence.update(record: inverse_assoc, attribute_name: attribute_name, position: position)
65
59
  end
66
60
  logger.info "ActiveSequence - Sequencing from #{self.class.name}: Done."
67
61
  end
68
- end
62
+ end
69
63
  end
70
64
  end
71
65
 
@@ -75,8 +69,8 @@ module ActiveKit
75
69
  elsif updater_via.is_a? Symbol
76
70
  reflected_klass(classname, updater_via)
77
71
  elsif updater_via.is_a? Hash
78
- klass = reflected_klass(classname, updater_via.key)
79
- updater_via.value.is_a?(Hash) ? search_base_klass(klass, updater_via.value) : reflected_klass(klass, updater_via.value)
72
+ klass = reflected_klass(classname, updater_via.keys.first)
73
+ updater_via.values.first.is_a?(Hash) ? search_base_klass(klass, updater_via.values.first) : reflected_klass(klass, updater_via.values.first)
80
74
  end
81
75
  end
82
76
 
@@ -87,11 +81,11 @@ module ActiveKit
87
81
  end
88
82
 
89
83
  def search_inverse_assoc(klass_object, updater_on)
90
- if updater_on.value.is_a?(Hash)
91
- klass_object = klass_object.public_send(updater_on.value.key)
92
- search_inverse_assoc(klass_object, updater_on.value)
84
+ if updater_on.values.first.is_a?(Hash)
85
+ klass_object = klass_object.public_send(updater_on.values.first.keys.first)
86
+ search_inverse_assoc(klass_object, updater_on.values.first)
93
87
  else
94
- klass_object.public_send(updater_on.value)
88
+ klass_object.public_send(updater_on.values.first)
95
89
  end
96
90
  end
97
91
  end
@@ -2,7 +2,7 @@ module ActiveKit
2
2
  module Sequence
3
3
  extend ActiveSupport::Autoload
4
4
 
5
- autoload :Sequencer
5
+ autoload :Sequence
6
6
  autoload :Wordbook
7
7
  end
8
8
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveKit
2
- VERSION = '0.1.3'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/active_kit.rb CHANGED
@@ -4,5 +4,8 @@ require "active_kit/engine"
4
4
  module ActiveKit
5
5
  extend ActiveSupport::Autoload
6
6
 
7
+ autoload :Activekiter
8
+ autoload :Loader
9
+ autoload :Relation
7
10
  autoload :Sequence
8
11
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activekit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - plainsource
@@ -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