road_to_el_duration 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e61bb17754de369f7def0f960b0912e74b90486f88339bfbf37be1540de592dc
4
+ data.tar.gz: 8d4914de53c504eaa680be2c83aae08a6778aafd5defbe37359f3e734d4a23c1
5
+ SHA512:
6
+ metadata.gz: 5aa9cce3f2e8ef38a0f70bd181965bfde0e2e998a3a49d655f5c93c4793ed91a3d8f5f2055bf72f62b00123f4193b5f222c53fbe95c761e46f7a151ff50b8b02
7
+ data.tar.gz: 65b61abea98d14685197eb37611ff04ee16f0363aafe4726ba8654262a37244d6dfcc14a3cd7aa9ae97df7a225f660613ab74d11b735e71f493eb4969ad0fead
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright Collin Jilbert
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # RoadToElDuration
2
+ Like a counter cache but for length in time attributes.
3
+
4
+ If the duration or length in time of an object needs to be calculated from the
5
+ duration or length in time of associated records this gem helps you achieve
6
+ that easily.
7
+
8
+ It handles automatic recalculations as child records are added,
9
+ removed, and transferred to other parent records.
10
+
11
+ It also comes with its own coder class that handles serializing and
12
+ deserializing the duration columns to and from instances of the
13
+ ActiveSupport::Duration class and the Ruby Integer class. This is an opt-in
14
+ feature so you don't have to use it if you don't want.
15
+
16
+ ## Usage
17
+ ```ruby
18
+ class Episode < ApplicationRecord
19
+ include RoadToElDuration::Calculations
20
+
21
+ belongs_to :series
22
+
23
+ serialize :duration, coder: RoadToElDuration::DurationCoder
24
+ updates_duration_of :series
25
+ end
26
+
27
+
28
+ class Series < ApplicationRecord
29
+ include RoadToElDuration::Calculations
30
+
31
+ has_many :episodes
32
+
33
+ serialize :duration, coder: RoadToElDuration::DurationCoder
34
+ calculates_duration_from :episodes
35
+ end
36
+ ```
37
+
38
+ ## Installation
39
+ Add this line to your application's Gemfile:
40
+
41
+ ```ruby
42
+ gem "road_to_el_duration"
43
+ ```
44
+
45
+ And then execute:
46
+ ```bash
47
+ $ bundle
48
+ ```
49
+ ## Contributing
50
+ Contribution directions go here.
51
+
52
+ ## License
53
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require "bundler/setup"
2
+
3
+ require "bundler/gem_tasks"
@@ -0,0 +1,95 @@
1
+ module RoadToElDuration
2
+ module Calculations
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ # This callback will update the duration of the current and any previous
7
+ # parent records. It will only update the parent records if the
8
+ # parent_to_update attribute is set.
9
+ #
10
+ after_save_commit :update_any_parent_durations
11
+
12
+ # These are class attribute accessors that will be set by the class
13
+ # methods below.
14
+ #
15
+ cattr_accessor :child_association_name,
16
+ :child_duration_column,
17
+ :parent_association_name,
18
+ :parent_duration_column
19
+ end
20
+
21
+ class_methods do
22
+ # This class method is used to set the association that the duration will be
23
+ # calculated from. It also sets the column that will be used from the
24
+ # child records to calculate the duration of the parent. The default
25
+ # column is :duration but you can set it to any column that will be used
26
+ # to calculate the duration.
27
+ #
28
+ def calculates_duration_from(child_association_name, column: :duration)
29
+ self.child_association_name= child_association_name
30
+ self.child_duration_column = column
31
+ end
32
+
33
+ # This class method is used to set the parent association that will be updated.
34
+ #
35
+ def updates_duration_of(parent_association, column: :duration)
36
+ self.parent_association_name = parent_association
37
+ self.parent_duration_column = column
38
+ end
39
+ end
40
+
41
+ # This method is used to update the duration of the record. It will sum the
42
+ # :duration_column of the associated records and update the :duration_column of
43
+ # the record. It is left as public API so that you can call it manually if
44
+ # needed.
45
+ #
46
+ def update_duration!
47
+ child_class = ActiveSupport::Inflector.singularize(child_association_name).camelize.constantize
48
+ duration_value[child_class.parent_duration_column] = calculate_duration
49
+ update!(**duration_value)
50
+ end
51
+
52
+ # This method is used to update the duration of the parent records. It will
53
+ # only update the parent records if the parent_to_update attribute is set.
54
+ # It will update the duration of the current parent record and any previous
55
+ # parent record if the record was transferred or removed from the collection.
56
+ #
57
+ def update_any_parent_durations
58
+ update_previous_parent_duration if transferred_or_removed_from_collection?
59
+ update_current_parent_duration if has_parent_record?
60
+ end
61
+
62
+ private
63
+
64
+ attr_writer :duration_value
65
+
66
+ def duration_value
67
+ @duration_value ||= {}
68
+ end
69
+
70
+ def calculate_duration
71
+ send(child_association_name).sum(child_duration_column)
72
+ end
73
+
74
+ def has_parent_record?
75
+ !!send(parent_association_name) if parent_association_name
76
+ end
77
+
78
+ def transferred_or_removed_from_collection?
79
+ send(:"#{parent_association_name}_id_previously_changed?") if parent_association_name
80
+ end
81
+
82
+ def previous_parent_id
83
+ send(:"#{parent_association_name}_id_previously_was")
84
+ end
85
+
86
+ def update_previous_parent_duration
87
+ return if previous_parent_id.nil?
88
+ parent_association_name.to_s.classify.constantize.find(previous_parent_id).update_duration!
89
+ end
90
+
91
+ def update_current_parent_duration
92
+ send(parent_association_name).update_duration!
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,27 @@
1
+ module RoadToElDuration
2
+ class DurationCoder
3
+ def self.dump(value)
4
+ value.to_i
5
+ end
6
+
7
+ def self.load(value)
8
+ initial_duration = ActiveSupport::Duration.build(value || 0)
9
+ ActiveSupport::Duration.new(initial_duration.to_i, convert_parts(initial_duration.parts))
10
+ end
11
+
12
+ def self.convert_parts(duration_parts)
13
+ new_duration_parts = {
14
+ hours: duration_parts.delete(:hours) || 0,
15
+ minutes: duration_parts.delete(:minutes) || 0
16
+ }
17
+ duration_parts.delete(:seconds)
18
+
19
+ # Take remaining parts (parts larger than hours) and convert to hours
20
+ duration_parts.each do |name, value|
21
+ new_duration_parts[:hours] += value.send(name).in_hours.to_i
22
+ end
23
+
24
+ new_duration_parts
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,4 @@
1
+ module RoadToElDuration
2
+ class Railtie < ::Rails::Railtie
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module RoadToElDuration
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,7 @@
1
+ require "road_to_el_duration/version"
2
+ require "road_to_el_duration/railtie"
3
+ require "road_to_el_duration/calculations"
4
+ require "road_to_el_duration/duration_coder"
5
+
6
+ module RoadToElDuration
7
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :road_to_el_duration do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: road_to_el_duration
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Collin Jilbert
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 7.1.3.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 7.1.3.2
27
+ description: Easily update the duration of a parent object when child objects are
28
+ added or removed.
29
+ email:
30
+ - cjilbert504@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - MIT-LICENSE
36
+ - README.md
37
+ - Rakefile
38
+ - lib/road_to_el_duration.rb
39
+ - lib/road_to_el_duration/calculations.rb
40
+ - lib/road_to_el_duration/duration_coder.rb
41
+ - lib/road_to_el_duration/railtie.rb
42
+ - lib/road_to_el_duration/version.rb
43
+ - lib/tasks/road_to_el_duration_tasks.rake
44
+ homepage: https://github.com/cjilbert504/road_to_el_duration
45
+ licenses:
46
+ - MIT
47
+ metadata:
48
+ homepage_uri: https://github.com/cjilbert504/road_to_el_duration
49
+ source_code_uri: https://github.com/cjilbert504/road_to_el_duration
50
+ changelog_uri: https://github.com/cjilbert504/road_to_el_duration/blob/main/CHANGELOG.md
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubygems_version: 3.5.9
67
+ signing_key:
68
+ specification_version: 4
69
+ summary: Easily update the duration of a parent object when child objects are added
70
+ or removed.
71
+ test_files: []