rails-minify 0.1.0 → 0.1.2

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: 32a43a0b86ec6d79152580e59ed32f5468ddd3d1a4e0865716f404bd542b566c
4
- data.tar.gz: fa640778b9324a8737ff1e809af7a101ff2e10b910677611de081b033678c983
3
+ metadata.gz: bf98d2d12a8005e5ef2755cd6bba97a32122a7dd2514518e9a749d1ba367af00
4
+ data.tar.gz: 878a2fab37d90963eb4b4d5924d7b3437847672741471d84ea6cefc686cb7ca1
5
5
  SHA512:
6
- metadata.gz: d078aaa82950d4407b91e82fcde444264496d72551db08177d629cdb61d5928ff23381462f23388cbf5db91c138cca78d1f79a870f0eeca794d178b0e8427af9
7
- data.tar.gz: e6ee0e7f39335eaba0d2adf4718a89dbdf52e8d1a8b993539ddfa3081631714bac16c5fc899b6f8dea5fd3cf12d667875843a1d73ccc524ecc72735c9e42834d
6
+ metadata.gz: 2baf13ba8db10c35cfaccfaf86b6c966b11555b9b232c1710da044a37dad166f96dee80cdc2380db98321a845c612e80f3a3648dbc515b31f9402a54bc393599
7
+ data.tar.gz: b26a83ac5f86fc456c18444e7eba578cb095fa897ee4bac9a508a10047a9164fc8d22197dc0ae6f7f2c7193ca32a437fe1b8fc35c7c9ab873d9091c936be57a0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.2 (2026-10-18)
4
+
5
+ - `minify:check` also fails on callback chains longer than `callback_limit` (default 5, `ApplicationController`'s callbacks excluded) and on model callbacks that save their own record again; `callback_limit_mode` and `callback_loops` set either to `:warn`. Works without the rest of rails-minify turned on; the manifest check runs only when there is a manifest.
6
+ - Requires activesupport-minimizer 0.1.1.
7
+
8
+ ## 0.1.1 (2026-10-18)
9
+
10
+ - `:omniauth` isn't installed when OmniAuth already skips requests that can't be the strategy's (a public `Strategy#passthrough?`, as in the version proposed upstream); its own helper no longer shares that name.
11
+
3
12
  ## 0.1.0 (2026-10-18)
4
13
 
5
14
  First release.
data/README.md CHANGED
@@ -14,6 +14,19 @@ config.rails_minify.enabled = true
14
14
  (`config.ar_minimizer.enums = false`, `config.rails_minify.patches = [:omniauth]`).
15
15
  Ruby 3.4+, Rails 8.0, 8.1 and main.
16
16
 
17
+ Turn it on in tests too, so a call to a method strict mode removed fails in CI
18
+ rather than in production. In development, strict mode alone is enough: the
19
+ same errors show up while you work, and the compiling parts, which don't
20
+ follow code reloads, stay off.
21
+
22
+ ```ruby
23
+ # config/environments/test.rb
24
+ config.rails_minify.enabled = true
25
+
26
+ # config/environments/development.rb
27
+ config.ar_minimizer.slim = true # strict mode, without the rest
28
+ ```
29
+
17
30
  ## Strict by default
18
31
 
19
32
  Active Record defines, for every column, a reader, a writer and 19 more
@@ -57,7 +70,7 @@ For parts of Rails and common gems that redo work on every request.
57
70
  Attachments that are Active Storage blobs, remote images or inline content
58
71
  are cached too: a blob without a caption contributes its filename, which a
59
72
  hit checks in one query (renamed or deleted: computed again). Other
60
- attachables aren't cached. In golf-buddy, 13% of all allocations on its
73
+ attachables aren't cached. In [Japan Voyage](https://japanvoyage.jp), 13% of all allocations on its
61
74
  pages came from it, and guides with images another 4.5%.
62
75
  * `:request_host`: `ActionDispatch::Request#host` runs a regexp substitution
63
76
  on every call, port or not, and Rails reads it several times per request.
@@ -67,11 +80,13 @@ For parts of Rails and common gems that redo work on every request.
67
80
  options on every request before looking at the path. Requests that can't
68
81
  be OmniAuth's go straight to the app. Only when that's certain up front:
69
82
  a session is present, not in test mode, no `other_phase` or callable
70
- paths, and the strategy doesn't override how paths are matched.
83
+ paths, and the strategy doesn't override how paths are matched. Not
84
+ installed when OmniAuth already does this itself (it then has a public
85
+ `Strategy#passthrough?`, as in the version proposed upstream).
71
86
 
72
87
  ## Numbers
73
88
 
74
- golf-buddy, 132 production pages, with everything on (strict mode after
89
+ Japan Voyage, 132 production pages, with everything on (strict mode after
75
90
  rubocop-minify's rewrites, all patches): identical HTML, and
76
91
  1,561,283 → 1,224,141 allocations per pass (−21.6%). The machine was too
77
92
  loaded for wall-clock times to mean much.
@@ -79,7 +94,26 @@ loaded for wall-clock times to mean much.
79
94
  ## Checks
80
95
 
81
96
  * `bin/rails minify:census`: how much of the app runs compiled, and why the rest doesn't.
82
- * `bin/rails minify:check`: callbacks naming methods that don't exist (for CI).
97
+ * `bin/rails minify:check` (for CI; works whether or not the rest of
98
+ rails-minify is on) fails on:
99
+ * callbacks naming methods that don't exist;
100
+ * callback chains with more than `callback_limit` (default 5) of the app's
101
+ own callbacks (Rails' and gems' don't count; controllers per action).
102
+ Callbacks inherited from `callback_limit_exclude` (default
103
+ `["ApplicationController"]`: time zone, locale, current user, the
104
+ per-request basics) don't count either. A base class over the limit is
105
+ reported once, with the classes that inherit it;
106
+ * model callbacks that call `save`, `update`, `touch`, ... on the record
107
+ they run for, which runs the chain again;
108
+ * an out-of-date manifest.
109
+
110
+ ```ruby
111
+ config.rails_minify.callback_limit = 8
112
+ config.rails_minify.callback_limit_exclude = ["ApplicationController", "Admin::BaseController"] # [] counts everything
113
+ config.rails_minify.callback_limit_mode = :warn # report, don't fail
114
+ config.rails_minify.callback_loops = :warn
115
+ config.rails_minify.allow_callback_loops = ["Trip#recalculate"] # guarded on purpose
116
+ ```
83
117
 
84
118
  ## Things found that are app config, not patches
85
119
 
@@ -4,9 +4,9 @@ module RailsMinify
4
4
  module Patches
5
5
  # ActionText::Content#to_plain_text walks the whole HTML tree with
6
6
  # Nokogiri on every call, and looks up the record behind every attachment:
7
- # in golf-buddy, 13% of all allocations on its pages came from it
8
- # (excerpts, meta descriptions, cards). The text is computed once per
9
- # distinct HTML and kept, up to MAX_BYTES of HTML.
7
+ # on Japan Voyage (japanvoyage.jp), 13% of all allocations on its pages
8
+ # came from it (excerpts, meta descriptions, cards). The text is computed
9
+ # once per distinct HTML and kept, up to MAX_BYTES of HTML.
10
10
  #
11
11
  # Without attachments the text depends on the HTML alone. An attachment
12
12
  # adds its record's text: for Active Storage blobs "[caption]" (from the
@@ -3,20 +3,29 @@
3
3
  module RailsMinify
4
4
  module Patches
5
5
  # Every OmniAuth strategy is a middleware that, on every request, dups
6
- # itself (and its Hashie::Mash options) before looking at the path: in
7
- # golf-buddy about 35k allocations per pass over its pages, none of them
8
- # on a login path. Requests that can't be OmniAuth's go straight to the
9
- # app; anything that might be (or that the strategy decides at runtime:
10
- # callable paths, other_phase, overridden path methods, test mode, a
11
- # missing session, which OmniAuth reports) runs OmniAuth as before.
6
+ # itself (and its Hashie::Mash options) before looking at the path: on
7
+ # Japan Voyage (japanvoyage.jp) about 35k allocations per pass over its
8
+ # pages, none of them on a login path. Requests that can't be OmniAuth's
9
+ # go straight to the app; anything that might be (or that the strategy
10
+ # decides at runtime: callable paths, other_phase, overridden path
11
+ # methods, test mode, a missing session, which OmniAuth reports) runs
12
+ # OmniAuth as before.
12
13
  module OmniAuthPassthrough
13
14
  # What decides whether a request is the strategy's. A strategy that
14
15
  # overrides any of these decides for itself: always run it.
15
16
  PATH_METHODS = %i[call! on_auth_path? on_request_path? on_callback_path? on_path? request_path
16
17
  callback_path current_path path_prefix script_name].freeze
17
18
 
18
- def self.install!
19
- OmniAuth::Strategy.prepend(self) unless OmniAuth::Strategy < self
19
+ def self.install!(strategy = OmniAuth::Strategy)
20
+ return if upstream?(strategy) # OmniAuth does this itself
21
+
22
+ strategy.prepend(self) unless strategy < self
23
+ end
24
+
25
+ # The same check in OmniAuth (sampokuokkanen/omniauth@skip-dup-off-auth-paths,
26
+ # proposed upstream) defines a public Strategy#passthrough?.
27
+ def self.upstream?(strategy = OmniAuth::Strategy)
28
+ strategy.public_method_defined?(:passthrough?) && !(strategy < self)
20
29
  end
21
30
 
22
31
  # Per strategy class: are all of PATH_METHODS OmniAuth's own?
@@ -28,14 +37,14 @@ module RailsMinify
28
37
  end
29
38
 
30
39
  def call(env)
31
- return super unless passthrough?(env)
40
+ return super unless minify_passthrough?(env)
32
41
 
33
42
  @app.call(env)
34
43
  end
35
44
 
36
45
  private
37
46
 
38
- def passthrough?(env)
47
+ def minify_passthrough?(env)
39
48
  return false if OmniAuth.config.test_mode || !env["rack.session"] || respond_to?(:other_phase)
40
49
  return false unless OmniAuthPassthrough.standard_paths?(self.class)
41
50
 
@@ -69,15 +69,39 @@ module RailsMinify
69
69
  end
70
70
  end
71
71
 
72
- desc "Fail on what would break at runtime or compile stale: missing callback targets, an out-of-date manifest"
72
+ desc "Fail on callback problems (missing targets, chains longer than callback_limit, " \
73
+ "callbacks that save their own record) and an out-of-date manifest"
73
74
  task check: :environment do
74
75
  app = prepare.call
75
- problems = AsMinimizer::Check.callback_targets(routed: AsMinimizer::Check.routed_actions(app.routes))
76
- missing = problems.select { it.status == :missing }
77
- missing.each { puts " #{it}" }
78
- manifest = ArMinimizer::Census.manifest_state(app.root, ArMinimizer::Index.from_models)
79
- puts "callback targets: #{missing.size} missing; manifest: #{manifest}"
80
- abort if missing.any? || manifest.start_with?("out of date")
76
+ options = app.config.rails_minify
77
+ routed = AsMinimizer::Check.routed_actions(app.routes)
78
+ failed = false
79
+ report = lambda do |title, items, mode|
80
+ next puts("#{title}: none") if items.empty?
81
+
82
+ puts "#{title}: #{items.size}#{" (warning)" if mode == :warn}"
83
+ items.each { puts " #{it}" }
84
+ failed ||= mode != :warn
85
+ end
86
+
87
+ missing = AsMinimizer::Check.callback_targets(routed: routed).select { it.status == :missing }
88
+ report.("callback targets naming no method", missing, :fail)
89
+
90
+ limit = options.callback_limit || 5
91
+ report.("callback chains with more than #{limit} of the app's callbacks",
92
+ AsMinimizer::Check.long_chains(limit: limit, root: app.root.to_s, routed: routed,
93
+ exclude: options.callback_limit_exclude.nil? ? ["ApplicationController"] : Array(options.callback_limit_exclude)),
94
+ (options.callback_limit_mode || :fail).to_sym)
95
+
96
+ report.("callbacks saving their own record",
97
+ AsMinimizer::Check.callback_loops(root: app.root.to_s, allow: Array(options.allow_callback_loops)), (options.callback_loops || :fail).to_sym)
98
+
99
+ if defined?(ArMinimizer::Census) && app.root.join("config/ar_minimizer.json").exist?
100
+ manifest = ArMinimizer::Census.manifest_state(app.root, ArMinimizer::Index.from_models)
101
+ puts "manifest: #{manifest}"
102
+ failed ||= manifest.start_with?("out of date")
103
+ end
104
+ abort if failed
81
105
  end
82
106
  end
83
107
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMinify
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-minify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sampo Kuokkanen
@@ -44,6 +44,9 @@ dependencies:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0.1'
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 0.1.1
47
50
  type: :runtime
48
51
  prerelease: false
49
52
  version_requirements: !ruby/object:Gem::Requirement
@@ -51,6 +54,9 @@ dependencies:
51
54
  - - "~>"
52
55
  - !ruby/object:Gem::Version
53
56
  version: '0.1'
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 0.1.1
54
60
  description: Turns on activerecord-, activesupport- and actionpack-minimizer, and
55
61
  patches parts of Rails and common gems that redo work on every request (Action Text
56
62
  plain text, Request#host, OmniAuth strategies).