activekit 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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