vident-view_component-caching 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0c92605001e18a9f49a3ba28db60fc0269bb78f74b3333b2484511dc4d240653
4
+ data.tar.gz: 4dd98bc48794cd45f023fdb71beb4b0e1035a1e4bbcd5c6397256d20bf5e1e95
5
+ SHA512:
6
+ metadata.gz: b619b40a8d2ad65ff8bf906cea5b303353de96cd2c7eeef7087d6de439913629e9127dda7e2e8ccf95cfb488af4dc371bcc2ed57f4646f133ca26349d6f7d6f9
7
+ data.tar.gz: 8a87104ad9b01147cc473dbea7b0e950d66d82be3839a223b6829df48bfe1051ada6ee5b1599901e20c77d520e2c6cdadb4d29a780a95eef9730cbb46e848d22
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Vident::ViewComponent::Caching
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem "vident-view_component-caching"
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install vident-view_component-caching
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ 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,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :vident_view_component_caching do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,8 @@
1
+ module Vident
2
+ module ViewComponent
3
+ module Caching
4
+ class Railtie < ::Rails::Railtie
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Vident
2
+ module ViewComponent
3
+ module Caching
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,145 @@
1
+ require "vident/view_component/caching/version"
2
+ require "vident/view_component/caching/railtie"
3
+
4
+ module Vident
5
+ module ViewComponent
6
+ # Rails fragment caching works by either expecting the cached key object to respond to `cache_key` or for that object
7
+ # to be an array or hash.
8
+ module Caching
9
+ extend ActiveSupport::Concern
10
+
11
+ class_methods do
12
+ def inherited(subclass)
13
+ subclass.instance_variable_set(
14
+ :@named_cache_key_attributes,
15
+ @named_cache_key_attributes.clone
16
+ )
17
+ super
18
+ end
19
+
20
+ def with_cache_key(*attrs, name: :_collection)
21
+ raise StandardError, "with_cache_key can only be used on components *without* slots as there is no eary way to track their content changes so too risky" if respond_to?(:slots?) && slots?
22
+ # Add view file to cache key
23
+ attrs << :component_modified_time
24
+ named_cache_key_includes(name, *attrs)
25
+ end
26
+
27
+ attr_reader :named_cache_key_attributes
28
+
29
+ # TypedComponents can be used with fragment caching, but you need to be careful! Read on...
30
+ #
31
+ # <% cache component do %>
32
+ # <%= render component %>
33
+ # <% end %>
34
+ #
35
+ # The most important point is that Rails cannot track dependencies on the component itself, so you need to
36
+ # be careful to be explicit on the attributes, and manually specify any sub Viewcomponent dependencies that the
37
+ # component has. The assumption is that the subcomponent takes any attributes from the parent, so the cache key
38
+ # depends on the parent component attributes. Otherwise changes to the parent or sub component views/Ruby class
39
+ # will result in different cache keys too. Of course if you invalidate all cache keys with a modifier on deploy
40
+ # then no need to worry about changing the cache key on component changes, only on attribute/data changes.
41
+ #
42
+ # A big caveat is that the cache key cannot depend on anything related to the view_context of the component (such
43
+ # as `helpers` as the key is created before the rending pipline is invoked (which is when the view_context is set).
44
+ def depends_on(*klasses)
45
+ @component_dependencies ||= []
46
+ @component_dependencies += klasses
47
+ end
48
+
49
+ attr_reader :component_dependencies
50
+
51
+ def component_modified_time
52
+ return @component_modified_time if Rails.env.production? && @component_modified_time
53
+ # FIXME: This could stack overflow if there are circular dependencies
54
+ deps = component_dependencies&.map(&:component_modified_time)&.join("-") || ""
55
+ @component_modified_time = deps + sidecar_view_modified_time + rb_component_modified_time
56
+ end
57
+
58
+ def sidecar_view_modified_time
59
+ return @sidecar_view_modified_time if Rails.env.production? && defined?(@sidecar_view_modified_time)
60
+ @sidecar_view_modified_time = ::File.exist?(template_path) ? ::File.mtime(template_path).to_i.to_s : ""
61
+ end
62
+
63
+ def rb_component_modified_time
64
+ return @rb_component_modified_time if Rails.env.production? && defined?(@rb_component_modified_time)
65
+ @rb_component_modified_time = ::File.exist?(component_path) ? ::File.mtime(component_path).to_i.to_s : ""
66
+ end
67
+
68
+ def template_path
69
+ File.join components_base_path, "#{virtual_path}.html.erb"
70
+ end
71
+
72
+ def component_path
73
+ File.join components_base_path, "#{virtual_path}.rb"
74
+ end
75
+
76
+ def components_base_path
77
+ ::Rails.configuration.view_component.view_component_path || "app/components"
78
+ end
79
+
80
+ private
81
+
82
+ def named_cache_key_includes(name, *attrs)
83
+ define_cache_key_method unless @named_cache_key_attributes
84
+ @named_cache_key_attributes ||= {}
85
+ @named_cache_key_attributes[name] = attrs
86
+ end
87
+
88
+ def define_cache_key_method
89
+ # If the presenter defines cache key setup then define the method. Otherwise Rails assumes this
90
+ # will return a valid key if the class will respond to this
91
+ define_method :cache_key do |n = :_collection|
92
+ if defined?(@cache_key)
93
+ return @cache_key[n] if @cache_key.key?(n)
94
+ else
95
+ @cache_key ||= {}
96
+ end
97
+ generate_cache_key(n)
98
+ @cache_key[n]
99
+ end
100
+ end
101
+ end
102
+
103
+ # Component modified time which is combined with other cache key attributes to generate cache key for an instance
104
+ def component_modified_time
105
+ self.class.component_modified_time
106
+ end
107
+
108
+ def cacheable?
109
+ respond_to? :cache_key
110
+ end
111
+
112
+ def cache_key_modifier
113
+ ENV["RAILS_CACHE_ID"]
114
+ end
115
+
116
+ def cache_keys_for_sources(key_attributes)
117
+ sources = key_attributes.flat_map { |n| n.is_a?(Proc) ? instance_eval(&n) : send(n) }
118
+ sources.compact.map do |item|
119
+ next if item == self
120
+ generate_item_cache_key_from(item)
121
+ end
122
+ end
123
+
124
+ def generate_item_cache_key_from(item)
125
+ if item.respond_to? :cache_key_with_version
126
+ item.cache_key_with_version
127
+ elsif item.respond_to? :cache_key
128
+ item.cache_key
129
+ elsif item.is_a?(String)
130
+ Digest::SHA1.hexdigest(item)
131
+ else
132
+ Digest::SHA1.hexdigest(Marshal.dump(item))
133
+ end
134
+ end
135
+
136
+ def generate_cache_key(index)
137
+ key_attributes = self.class.named_cache_key_attributes[index]
138
+ return nil unless key_attributes
139
+ key = "#{self.class.name}/#{cache_keys_for_sources(key_attributes).join("/")}"
140
+ raise StandardError, "Cache key for key #{key} is blank!" if key.blank?
141
+ @cache_key[index] = cache_key_modifier.present? ? "#{key}/#{cache_key_modifier}" : key
142
+ end
143
+ end
144
+ end
145
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vident-view_component-caching
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Stephen Ierodiaconou
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-04-02 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'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '8'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '7'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '8'
33
+ - !ruby/object:Gem::Dependency
34
+ name: vident-view_component
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 0.1.0
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '1'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 0.1.0
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '1'
53
+ description: Cache key computation for Vident components with ViewComponent
54
+ email:
55
+ - stevegeek@gmail.com
56
+ executables: []
57
+ extensions: []
58
+ extra_rdoc_files: []
59
+ files:
60
+ - README.md
61
+ - Rakefile
62
+ - lib/tasks/vident/view_component/caching_tasks.rake
63
+ - lib/vident/view_component/caching.rb
64
+ - lib/vident/view_component/caching/railtie.rb
65
+ - lib/vident/view_component/caching/version.rb
66
+ homepage: https://github.com/stevegeek/vident-view_component-caching
67
+ licenses:
68
+ - MIT
69
+ metadata:
70
+ homepage_uri: https://github.com/stevegeek/vident-view_component-caching
71
+ source_code_uri: https://github.com/stevegeek/vident-view_component-caching
72
+ changelog_uri: https://github.com/stevegeek/vident-view_component-caching/blob/main/CHANGELOG.md
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 3.4.6
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Cache key computation for Vident components with ViewComponent
92
+ test_files: []