activerecord-minimizer 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7993bf021f8de2ed44f37b3dd541d6644b1fd1d38817acaecf424852713acb2a
4
- data.tar.gz: 0c520dcb7ca0543b4ac891ea9abced9968d0fec36edd258c9a47dc7ea33f962d
3
+ metadata.gz: b96e595f334bcacd836276d8ff508f885079a41d045ef4ffdcc743689ae6469b
4
+ data.tar.gz: 7ecfa22211db6dc240d50dbc20cdcf99f6e133e8e4ba416e54a477c2b3a6a817
5
5
  SHA512:
6
- metadata.gz: faa673f2b296a034bbca5c927642dcde2f3f38c6e689b825c8f6884fbe0810a7ec0514f3669a685fa6f81487b578d4a41345f38de5ca3f327851c0d195abd1c2
7
- data.tar.gz: '09b436a70b52965449931ebc407b9396ca7068233644025de33516f56148f0c31507cd5f265a4a3884cec901482fe9c1dc3ee02e9b42e28accd41f077b332d73'
6
+ metadata.gz: 3cd2f5496af0696ee69d1eea8e49573c5cd3df9668d34fae090746f8b9f86311c7f3c83caca487eecf639dc6d2e33e49d107f41f7b9c73aa216cc5886cf07f0b
7
+ data.tar.gz: 55114753dad4d0ffad49945183424379059bca3637f0d24517e7bcc6d86cf475646bec3d4e2cc499c76b79b3d3ec900555d41d1a2e267237f3b05695d9472428
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 (2026-11-05)
4
+
5
+ - Removed `config.ar_minimizer.enums` (`ArMinimizer::Enums`). It made enum predicates faster in a benchmark but changed nothing measurable in production, and it no longer worked on Rails main. Setting it does nothing now. `ar_minimizer:census` no longer counts enum methods.
6
+
3
7
  ## 0.2.0 (2026-10-20)
4
8
 
5
9
  - With `load_time`, the manifest's index (10-20 MB on a large app) is let go once an eager-loading boot is done, before a preloading server forks; a file loaded later indexes the manifest again.
data/README.md CHANGED
@@ -56,14 +56,6 @@ first call to one generates it on that model.
56
56
  Turn `slim` on in development and tests as well as production: the
57
57
  errors then show up while you work and in CI. Slim follows code reloads.
58
58
 
59
- ## Enums
60
-
61
- `config.ar_minimizer.enums = true` replaces the closures Rails defines for
62
- enum predicates and bang methods, which build and intern the
63
- `<name>_for_database` symbol on every call, with ordinary methods carrying
64
- the enum's values: `def published? = public_send(:status_for_database) == 1`.
65
- 1.3–1.6× faster predicates; non-finite float values keep Rails' closures.
66
-
67
59
  ## Experimental
68
60
 
69
61
  Each is off unless set. They are faster per call in benchmarks, but made no
@@ -105,7 +97,7 @@ Where it compiles:
105
97
  `app/` and `lib/` in place instead, like explode_sqlite. Production only (or
106
98
  `FORCE=1`); `DRY_RUN=1` previews.
107
99
 
108
- All three read the **manifest** (strict mode and enums don't need one), `config/ar_minimizer.json`, written by
100
+ All three read the **manifest** (strict mode doesn't need one), `config/ar_minimizer.json`, written by
109
101
  `bin/rails ar_minimizer:manifest`: per model its columns and their query kind,
110
102
  the attribute method patterns, hand-written methods, superclass, app modules,
111
103
  associations, scopes, and names it defines another way (an enum predicate
@@ -154,7 +146,6 @@ without, the same traffic for an hour, October 2026):
154
146
  | part | result |
155
147
  |---|---|
156
148
  | strict mode | no call to a removed method; the same latency and memory |
157
- | enums | the same median latency; no change in allocations on these pages |
158
149
  | small records | no difference: tens of records per request |
159
150
  | compiling in views | no faster, ~22 MB more per worker |
160
151
  | compiling at load time | ~12% more CPU per request, not reproduced locally; measured before the app was preloaded, so worth measuring again |
@@ -1,15 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArMinimizer
4
- # What the attribute-method and enum compilers cover in an app.
4
+ # What the attribute-method compilers cover in an app.
5
5
  module Census
6
- Result = Data.define(:models, :columns, :stock_methods, :generated_methods, :enum_methods, :enum_compiled,
7
- :sites, :files, :manifest) do
6
+ Result = Data.define(:models, :columns, :stock_methods, :generated_methods, :sites, :files, :manifest) do
8
7
  def lines(verbose: false)
9
8
  [
10
9
  "models: #{models}, #{columns} columns",
11
10
  "attribute methods: #{stock_methods} in stock Rails, #{generated_methods || "n/a (slim off)"} generated with slim",
12
- "enum methods: #{enum_compiled}/#{enum_methods} compiled",
13
11
  "attribute call sites: #{sites} compilable in #{files} files under app/ and lib/",
14
12
  "manifest: #{manifest}",
15
13
  ]
@@ -24,22 +22,14 @@ module ArMinimizer
24
22
  models.each(&:define_attribute_methods)
25
23
  models.sum { it.send(:generated_attribute_methods).instance_methods(false).size }
26
24
  end
27
- enum_methods = enum_compiled = 0
28
- models.each do |model|
29
- mod = model.instance_variable_get(:@_enum_methods_module) or next
30
- mod.instance_methods(false).each do |name|
31
- enum_methods += 1
32
- enum_compiled += 1 if mod.instance_method(name).source_location&.first.to_s.start_with?("enum ")
33
- end
34
- end
35
25
  sites = files = 0
36
26
  Dir.glob(File.join(root.to_s, "{app,lib}", "**", "*.rb")).each do |file|
37
27
  n = Rewriter.new(index: index, path: file, guards: guards).rewrite(File.read(file)).sites
38
28
  sites += n
39
29
  files += 1 if n.positive?
40
30
  end
41
- Result.new(models.size, models.sum { it.attribute_names.size }, stock, generated, enum_methods, enum_compiled,
42
- sites, files, manifest_state(root, index))
31
+ Result.new(models.size, models.sum { it.attribute_names.size }, stock, generated, sites, files,
32
+ manifest_state(root, index))
43
33
  end
44
34
 
45
35
  def self.manifest_state(root, index)
@@ -10,7 +10,6 @@ module ArMinimizer
10
10
  # config.ar_minimizer.strict = false # ... and generate the rest when first called, instead of removing them
11
11
  # config.ar_minimizer.load_time = true # compile app/ and lib/ as they load (needs the manifest)
12
12
  # config.ar_minimizer.views = true # compile templates as ActionView loads them
13
- # config.ar_minimizer.enums = true # enum predicates/bang methods as plain methods
14
13
  # config.ar_minimizer.small_records = true # no Hashes for records that never fill them
15
14
  # config.ar_minimizer.guards = true # also compile calls on receivers of unknown class, behind a class check
16
15
  #
@@ -30,7 +29,6 @@ module ArMinimizer
30
29
  manifest = -> { ArMinimizer::Manifest.parse(manifest_json) } if manifest_json
31
30
 
32
31
  ActiveSupport.on_load(:active_record) do
33
- ArMinimizer::Enums.install! if options.enums
34
32
  ArMinimizer::SmallRecords.install! if options.small_records
35
33
  ArMinimizer::Slim.enable!(keep_methods: keep_methods, strict: options.strict != false) if options.slim
36
34
  ArMinimizer::Profile.start!(ENV["AR_MINIMIZER_PROFILE"]) if ENV["AR_MINIMIZER_PROFILE"]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArMinimizer
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/ar_minimizer.rb CHANGED
@@ -25,7 +25,6 @@ module ArMinimizer
25
25
  autoload :Views, "ar_minimizer/views"
26
26
  autoload :Profile, "ar_minimizer/profile"
27
27
  autoload :Manifest, "ar_minimizer/manifest"
28
- autoload :Enums, "ar_minimizer/enums"
29
28
  autoload :Census, "ar_minimizer/census"
30
29
  autoload :SmallRecords, "ar_minimizer/small_records"
31
30
  autoload :Loader, "ar_minimizer/loader"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-minimizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sampo Kuokkanen
@@ -59,8 +59,7 @@ dependencies:
59
59
  version: '0.4'
60
60
  description: Generates only the reader and writer per Active Record column (strict
61
61
  mode removes the other 19 attribute methods), compiles call sites to the calls those
62
- methods stood for, turns enum closures into plain methods and stops records allocating
63
- Hashes they never fill.
62
+ methods stood for and stops records allocating Hashes they never fill.
64
63
  executables: []
65
64
  extensions: []
66
65
  extra_rdoc_files: []
@@ -72,7 +71,6 @@ files:
72
71
  - lib/ar_minimizer.rb
73
72
  - lib/ar_minimizer/build.rb
74
73
  - lib/ar_minimizer/census.rb
75
- - lib/ar_minimizer/enums.rb
76
74
  - lib/ar_minimizer/index.rb
77
75
  - lib/ar_minimizer/loader.rb
78
76
  - lib/ar_minimizer/manifest.rb
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ArMinimizer
4
- # Enum predicates and bang methods as ordinary methods.
5
- #
6
- # Rails defines them with closures, and each predicate call builds and
7
- # interns the `<name>_for_database` symbol before calling it:
8
- #
9
- # # def active?() status_for_database == 0 end (Rails' own comment)
10
- # define_method("#{value_method_name}?") { public_send(:"#{name}_for_database") == value }
11
- #
12
- # Here the enum's literal data goes into the method source instead, as
13
- # Roundhouse does for macros with literal arguments:
14
- #
15
- # def active? = public_send(:status_for_database) == 0
16
- # def active! = update!("status" => 0)
17
- #
18
- # Rails still runs first (conflict detection, scopes); only the two methods
19
- # are replaced. Rails allows booleans, integers, floats, symbols and strings
20
- # as values; non-finite floats, and method names that aren't plain
21
- # identifiers, keep Rails' closures.
22
- module Enums
23
- IDENTIFIER = /\A[a-zA-Z_][a-zA-Z0-9_]*\z/
24
-
25
- class << self
26
- # Before models load (their class bodies declare the enums).
27
- def install!
28
- @enabled = true
29
- mod = ActiveRecord::Enum.const_get(:EnumMethods)
30
- mod.prepend(Definer) unless mod < Definer
31
- end
32
-
33
- def disable! = @enabled = false
34
-
35
- def enabled? = @enabled == true
36
-
37
- def literal(value)
38
- case value
39
- when Integer, String, Symbol, true, false, nil then value.inspect
40
- when Float then value.inspect if value.finite?
41
- end
42
- end
43
- end
44
-
45
- module Definer
46
- private
47
-
48
- def define_enum_methods(name, value_method_name, value, scopes, instance_methods)
49
- super
50
- return unless instance_methods && Enums.enabled?
51
- return unless value_method_name.match?(IDENTIFIER) && (literal = Enums.literal(value))
52
-
53
- remove_method(:"#{value_method_name}?", :"#{value_method_name}!")
54
- module_eval(<<~RUBY, "enum #{klass.name}.#{name}", 1)
55
- def #{value_method_name}? = public_send(#{:"#{name}_for_database".inspect}) == #{literal}
56
- def #{value_method_name}! = update!(#{name.inspect} => #{literal})
57
- RUBY
58
- end
59
- end
60
- end
61
- end