view_component-fragment_caching 0.2.1

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: cc762ffb0feb715f3c3bf3d621c783871453926765109c40d4cd827f50494580
4
+ data.tar.gz: 717f0a81506a140d71d0b717149662fe073eb006bdfd0cbeae59f2419bf9a6a3
5
+ SHA512:
6
+ metadata.gz: 642b6eef5c8669122224a26b1090f3bb1ce242c1b322126c967effc4361048014de35486007aeb8d7f7a9f3dff7b60ce8c4e7fa100cc9391de787112944c30ae
7
+ data.tar.gz: a523f790eaf7747ab425a5d5279294fa5f96bfcf3d958fe50f1472ecc3c5083cf13e882e0ccebee5ea7ff4b2620a4b7062751ed88680b060a8c7609688080617
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022 Patrick Arnett
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,62 @@
1
+ # ViewComponent::FragmentCaching
2
+ With fragment caching in Rails, updates to a partial's source code will automatically bust
3
+ appropriate caches in which the partial is detectable as a dependency.
4
+
5
+ This gem augments ActionView's fragment caching strategy to detect and parse view components. In addition to digesting a
6
+ component's view file (if present), it will also digest the component's ruby file and those of any superclasses
7
+ descended from `ViewComponent::Base`.
8
+
9
+ ## Installation
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem "view_component-fragment_caching"
14
+ ```
15
+
16
+ And then execute:
17
+ ```bash
18
+ $ bundle
19
+ ```
20
+
21
+ Or install it yourself as:
22
+ ```bash
23
+ $ gem install view_component-fragment_caching
24
+ ```
25
+
26
+ ## Configuration
27
+ By default, view components will be detected in `ViewComponent::Base.view_component_path` (`app/components` typically).
28
+ This can be configured in an initializer:
29
+
30
+ ```ruby
31
+ ViewComponent::FragmentCaching.configure do |c|
32
+ c.view_component_paths = %w(
33
+ app/components
34
+ app/additional_components
35
+ )
36
+ end
37
+ ```
38
+
39
+ ## Use
40
+ It is important that naming conventions are followed. The tracker will ignore components whose class names do not end with "Component".
41
+
42
+ #### Render dependencies
43
+ ```erb
44
+ <%= render Users::AuthorComponent.new(...) %>
45
+ <%= render Users::AuthorComponent.with_collection(...) %>
46
+ ```
47
+
48
+ #### Explicit dependencies
49
+ ```erb
50
+ <%# View Component Dependency: Users::AuthorComponent %>
51
+ <%= render @author %>
52
+ ```
53
+
54
+ ## Contributing
55
+ Please follow conventions and write tests.
56
+ ```bash
57
+ $ bundle exec rspec
58
+ $ bundle exec rubocop
59
+ ```
60
+
61
+ ## License
62
+ 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,8 @@
1
+ require 'bundler/setup'
2
+
3
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
4
+ load 'rails/tasks/engine.rake'
5
+
6
+ load 'rails/tasks/statistics.rake'
7
+
8
+ require 'bundler/gem_tasks'
@@ -0,0 +1,19 @@
1
+ ActiveSupport.on_load :action_controller do
2
+ next unless self == ActionController::Base
3
+
4
+ ViewComponent::FragmentCaching.initialize! context: self
5
+ end
6
+
7
+ Rails.application.reloader.to_prepare do
8
+ ActiveSupport.on_load :action_view do
9
+ ActiveSupport.on_load :after_initialize do
10
+ ActionView::DependencyTracker::ERBTracker.prepend ViewComponent::FragmentCaching::Trackers::ViewComponentTracking
11
+ ActionView::Digestor::Node.prepend ViewComponent::FragmentCaching::Digestors::WithViewComponentRb
12
+
13
+ ViewComponent::FragmentCaching::Resolvers::ViewComponentResolver::VIEW_COMPONENT_RUBY_HANDLER.tap do |vc_rb|
14
+ ActionView::Template.register_template_handler vc_rb, ActionView::Template::Handlers::ERB.new
15
+ ActionView::DependencyTracker.register_tracker vc_rb, ActionView::DependencyTracker::ERBTracker
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ require 'view_component'
2
+
3
+ module ViewComponent
4
+ module FragmentCaching
5
+ class Configuration
6
+ attr_reader :view_component_paths
7
+
8
+ def initialize
9
+ self.view_component_path = ::ViewComponent::Base.view_component_path
10
+ end
11
+
12
+ def view_component_paths=(path_or_paths)
13
+ @view_component_paths = Array(path_or_paths)
14
+ end
15
+ alias view_component_path= view_component_paths=
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,80 @@
1
+ module ViewComponent
2
+ module FragmentCaching
3
+ module Digestors
4
+ module WithViewComponentRb
5
+ class << self
6
+ def prepended(mod)
7
+ mod.singleton_class.prepend ClassMethods
8
+ end
9
+ end
10
+
11
+ module ClassMethods
12
+ def create(name, logical_name, template, partial)
13
+ klass = partial ? ActionView::Digestor::Partial : ActionView::Digestor::Node
14
+ children = ruby_nodes name, template, klass
15
+ klass.new name, logical_name, template, children
16
+ end
17
+
18
+ private
19
+
20
+ def ruby_nodes(name, template, klass)
21
+ identifier = template.identifier
22
+ if identifier.end_with?('.rb') || !identifier.match?(view_component_path_regex) ||
23
+ (component_class = name.classify.safe_constantize).nil?
24
+
25
+ return []
26
+ end
27
+
28
+ view_component_ancestors(component_class).map do |ancestor|
29
+ anc_identifier = ancestor.source_location
30
+ anc_logical_name = ancestor.name.underscore
31
+ view_component_ruby_node anc_identifier, anc_logical_name, template, klass
32
+ end
33
+ end
34
+
35
+ def view_component_path_regex
36
+ @view_component_path_regex ||=
37
+ begin
38
+ paths =
39
+ ViewComponent::FragmentCaching.view_component_paths.map do |path|
40
+ "/#{path}/".gsub Regexp.new('/{2,}'), '/'
41
+ end
42
+ Regexp.new paths.join '|'
43
+ end
44
+ end
45
+
46
+ def view_component_ancestors(component_class)
47
+ ancestors = component_class.ancestors
48
+ return [] unless ancestors.include? ViewComponent::Base
49
+
50
+ ancestors.each_with_object [] do |ancestor, memo|
51
+ return memo if ancestor == ViewComponent::Base
52
+
53
+ memo << ancestor if ancestor.is_a? Class
54
+ end
55
+ end
56
+
57
+ def view_component_ruby_node(identifier, logical_name, template, klass)
58
+ "#{identifier.split('.').first}.rb".then do |rb_identifier|
59
+ next unless File.exist? rb_identifier
60
+
61
+ rb_source = File.read rb_identifier
62
+ rb_template = new_ruby_template rb_source, rb_identifier, template, logical_name
63
+ klass.new logical_name, logical_name, rb_template, []
64
+ end
65
+ end
66
+
67
+ def new_ruby_template(rb_source, rb_identifier, template, virtual_path)
68
+ ActionView::Template.new rb_source,
69
+ rb_identifier,
70
+ template.handler,
71
+ locals: template.locals,
72
+ format: template.format,
73
+ variant: template.variant,
74
+ virtual_path: virtual_path
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,7 @@
1
+ module ViewComponent
2
+ module FragmentCaching
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace ViewComponent::FragmentCaching
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,129 @@
1
+ require 'action_view'
2
+
3
+ module ViewComponent
4
+ module FragmentCaching
5
+ module Resolvers
6
+ class ViewComponentResolver < ActionView::FileSystemResolver
7
+ VIEW_COMPONENT_RUBY_HANDLER = :vc_rb
8
+ public_constant :VIEW_COMPONENT_RUBY_HANDLER
9
+
10
+ class PathParser < ActionView::Resolver::PathParser
11
+ class MatchedAttributes
12
+ FORMATS = (ActionView::Template::Types.symbols | %i(rb)).map(&Regexp.method(:escape)).join('|').freeze
13
+ private_constant :FORMATS
14
+
15
+ HANDLERS = ActionView::Template::Handlers.extensions.map(&Regexp.method(:escape)).join('|').freeze
16
+ private_constant :HANDLERS
17
+
18
+ LOCALES = '(?!rb)[a-z]{2}(?:-[A-Z]{2})?'.freeze
19
+ private_constant :LOCALES
20
+
21
+ VARIANTS = '[^.]*'.freeze
22
+ private_constant :VARIANTS
23
+
24
+ MATCH_NAMES = %i(prefix partial action locale format variant handler).freeze
25
+ private_constant :MATCH_NAMES
26
+
27
+ REGEX = %r{
28
+ \A
29
+ (?:(?<prefix>.*)/)?
30
+ (?<partial>_)?
31
+ (?<action>.*?)
32
+ (?:\.(?<locale>#{LOCALES}))??
33
+ (?:\.(?<format>#{FORMATS}))??
34
+ (?:\+(?<variant>#{VARIANTS}))??
35
+ (?:\.(?<handler>#{HANDLERS}))?
36
+ \z
37
+ }x.freeze
38
+ private_constant :REGEX
39
+
40
+ delegate :[], to: :match
41
+
42
+ def initialize(path)
43
+ @match = REGEX.match path
44
+ end
45
+
46
+ def format
47
+ matched_sym :format
48
+ end
49
+
50
+ def handler
51
+ matched_sym(:handler) || (VIEW_COMPONENT_RUBY_HANDLER if format == :rb)
52
+ end
53
+
54
+ def locale
55
+ matched_sym :locale
56
+ end
57
+
58
+ def variant
59
+ matched_sym :variant
60
+ end
61
+
62
+ def method_missing(method_name, *)
63
+ match[method_name] if MATCH_NAMES.include? method_name
64
+ end
65
+
66
+ def respond_to_missing?(method_name)
67
+ MATCH_NAMES.include? method_name
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :match
73
+
74
+ def matched_sym(key)
75
+ match[key]&.to_sym
76
+ end
77
+ end
78
+ private_constant :MatchedAttributes
79
+
80
+ def parse(path)
81
+ match = MatchedAttributes.new path
82
+ template_path = ActionView::TemplatePath.build match.action, match.prefix || '', !match.partial.nil?
83
+ details = ActionView::TemplateDetails.new match.locale, match.handler, match.format, match.variant
84
+ ParsedPath.new template_path, details
85
+ end
86
+ end
87
+ private_constant :PathParser
88
+
89
+ def initialize(path)
90
+ super
91
+ override_path_parser
92
+ end
93
+
94
+ def clear_cache
95
+ super
96
+ override_path_parser
97
+ end
98
+
99
+ # def find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])
100
+ def find_all(*args)
101
+ name = args.fetch 0
102
+ prefix = args.fetch 1, nil
103
+ partial = false
104
+ details = args.fetch 3, {}
105
+ given_key = args.fetch 4, nil
106
+ locals = args.fetch 5, []
107
+
108
+ key = build_key given_key, details
109
+ super name, prefix, partial, details, key, locals
110
+ end
111
+
112
+ private
113
+
114
+ def override_path_parser
115
+ @path_parser = PathParser.new
116
+ end
117
+
118
+ def build_key(key, details)
119
+ (key || ActionView::TemplateDetails::Requested.new(**details)).then do |k|
120
+ ActionView::TemplateDetails::Requested.new formats: k.formats | %i(rb),
121
+ handlers: k.handlers,
122
+ locale: k.locale,
123
+ variants: k.variants
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,96 @@
1
+ module ViewComponent
2
+ module FragmentCaching
3
+ module Trackers
4
+ module ViewComponentTracking
5
+ EXPLICIT_VIEW_COMPONENT_DEPENDENCY = /# View Component Dependency: (\S+)/.freeze
6
+ private_constant :EXPLICIT_VIEW_COMPONENT_DEPENDENCY
7
+
8
+ CAMEL_PHRASE = /(?:([A-Z]+[a-z]*[0-9]*)+)/.freeze
9
+ private_constant :CAMEL_PHRASE
10
+
11
+ MODULE_NAME = /(?:((::)?#{CAMEL_PHRASE}+)+)/.freeze
12
+ private_constant :MODULE_NAME
13
+
14
+ VIEW_COMPONENT_NAME = /(?:#{MODULE_NAME}Component)/.freeze
15
+ private_constant :VIEW_COMPONENT_NAME
16
+
17
+ MODULE_NAME_END = /(?:\b[^:])/.freeze
18
+ private_constant :MODULE_NAME_END
19
+
20
+ INVOKE_METHOD = /(?:\s*\.\s*(((public_)?send?(\s*\(?\s*):)?))/.freeze
21
+ private_constant :INVOKE_METHOD
22
+
23
+ INITIALIZE_METHOD_NAME = /(?:\b(new|with_collection)\b)/.freeze
24
+ private_constant :INITIALIZE_METHOD_NAME
25
+
26
+ VIEW_COMPONENT_RENDER_ARGUMENTS = /
27
+ \A
28
+ (?:\s*\(?\s*)
29
+ (?<view_component>#{VIEW_COMPONENT_NAME})
30
+ (?:#{INVOKE_METHOD})
31
+ (?:#{INITIALIZE_METHOD_NAME})
32
+ /xm.freeze
33
+ private_constant :VIEW_COMPONENT_RENDER_ARGUMENTS
34
+
35
+ CLASS_INHERITANCE = /(?:\s*\bclass\s+#{MODULE_NAME}\s*<\s*)/.freeze
36
+ private_constant :CLASS_INHERITANCE
37
+
38
+ VIEW_COMPONENT_INHERITANCE_DEPENDENCY = /
39
+ (?:#{CLASS_INHERITANCE})
40
+ (?<view_component>#{VIEW_COMPONENT_NAME})
41
+ (?:#{MODULE_NAME_END})
42
+ /xm.freeze
43
+ private_constant :VIEW_COMPONENT_INHERITANCE_DEPENDENCY
44
+
45
+ def dependencies
46
+ render_dependencies |
47
+ explicit_dependencies |
48
+ view_component_inheritance_dependencies |
49
+ explicit_view_component_dependencies
50
+ end
51
+
52
+ private
53
+
54
+ def render_dependencies
55
+ [].tap do |render_dependencies|
56
+ render_calls = source.split(/\brender\b/).drop(1)
57
+
58
+ render_calls.each do |arguments|
59
+ add_dependencies render_dependencies, arguments, self.class::LAYOUT_DEPENDENCY
60
+ add_dependencies render_dependencies, arguments, self.class::RENDER_ARGUMENTS
61
+ add_dependencies render_dependencies, arguments, VIEW_COMPONENT_RENDER_ARGUMENTS
62
+ end
63
+ end
64
+ end
65
+
66
+ def add_dependencies(render_dependencies, arguments, pattern)
67
+ arguments.scan pattern do
68
+ match = Regexp.last_match.named_captures.symbolize_keys
69
+ add_dynamic_dependency render_dependencies, match[:dynamic]
70
+ add_static_dependency render_dependencies, match[:static], match[:quote]
71
+ add_view_component_dependency render_dependencies, match[:view_component]
72
+ end
73
+ end
74
+
75
+ def add_view_component_dependency(dependencies, dependency)
76
+ return if dependency.blank?
77
+
78
+ path = dependency.underscore
79
+ dependencies << path unless dependencies.include? path
80
+ end
81
+
82
+ def view_component_inheritance_dependencies
83
+ scan_source VIEW_COMPONENT_INHERITANCE_DEPENDENCY
84
+ end
85
+
86
+ def explicit_view_component_dependencies
87
+ scan_source EXPLICIT_VIEW_COMPONENT_DEPENDENCY
88
+ end
89
+
90
+ def scan_source(pattern)
91
+ source.scan(pattern).flatten.uniq.map(&:underscore)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,6 @@
1
+ module ViewComponent
2
+ module FragmentCaching
3
+ VERSION = '0.2.1'.freeze
4
+ public_constant :VERSION
5
+ end
6
+ end
@@ -0,0 +1,32 @@
1
+ require 'action_view/dependency_tracker/erb_tracker'
2
+ Dir[File.expand_path './fragment_caching/**/*.rb', __dir__].sort.each(&method(:require))
3
+
4
+ module ViewComponent
5
+ module FragmentCaching
6
+ class << self
7
+ delegate :view_component_paths, to: :configuration
8
+
9
+ def configuration
10
+ @configuration ||= Configuration.new
11
+ end
12
+
13
+ def configure
14
+ yield configuration
15
+ end
16
+
17
+ def initialize!(context:)
18
+ prepend_view_component_paths context
19
+ end
20
+
21
+ private
22
+
23
+ def prepend_view_component_paths(context)
24
+ full_paths = view_component_paths.map(&Rails.root.method(:join))
25
+ Dir[*full_paths].each do |dir|
26
+ resolver = Resolvers::ViewComponentResolver.new dir
27
+ context.prepend_view_path resolver
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: view_component-fragment_caching
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Patrick Arnett
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-06-17 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.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '7.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: view_component
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.43'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.43'
41
+ - !ruby/object:Gem::Dependency
42
+ name: capybara
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.36'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.36'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.26'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.26'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.14'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.14'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2.10'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.10'
125
+ description: Monkey patch ActionView to track and digest view components within cached
126
+ fragments.
127
+ email:
128
+ - patrick.a.arnett@gmail.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - MIT-LICENSE
134
+ - README.md
135
+ - Rakefile
136
+ - config/initializers/view_component/fragment_caching.rb
137
+ - lib/view_component/fragment_caching.rb
138
+ - lib/view_component/fragment_caching/configuration.rb
139
+ - lib/view_component/fragment_caching/digestors/with_view_component_rb.rb
140
+ - lib/view_component/fragment_caching/engine.rb
141
+ - lib/view_component/fragment_caching/resolvers/view_component_resolver.rb
142
+ - lib/view_component/fragment_caching/trackers/view_component_tracking.rb
143
+ - lib/view_component/fragment_caching/version.rb
144
+ homepage:
145
+ licenses:
146
+ - MIT
147
+ metadata:
148
+ source_code_uri: https://www.github.com/patrickarnett/view_component-fragment_caching
149
+ changelog_uri: https://www.github.com/patrickarnett/view_component-fragment_caching/blob/main/CHANGELOG.md
150
+ rubygems_mfa_required: 'true'
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: 2.6.0
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ requirements: []
166
+ rubygems_version: 3.2.22
167
+ signing_key:
168
+ specification_version: 4
169
+ summary: Bust fragment caches when view components update
170
+ test_files: []