rails-explicit_override 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: 7d08fc1fad8e50f31008de96e6cbfcd5ba4b50bf7313cdbe0ff1766444e20a34
4
+ data.tar.gz: fcf10efaa1b06ea96f51fdf16091e9053837d81e84bc9775436205e726c2adc0
5
+ SHA512:
6
+ metadata.gz: 676707469dacce3844c57253e36418398d43cfd25aaad3b1361f3383c4ca1610e9e11d02a477fecbe9b11bce8f6240773c3bd020dd5ac2b0456ef1bc2964ef88
7
+ data.tar.gz: 48f9f1f74be43f4bdbee8c9974441c6439e764b7ce624329430be1764b08a49bf3074cb290f3e438b0880b2928e56501e3e40adfa8215068ef6f960b60fc6f99
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026-present Kevin Newton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # rails-explicit_override
2
+
3
+ [![Build Status](https://github.com/kddnewton/rails-explicit_override/workflows/Main/badge.svg)](https://github.com/kddnewton/rails-explicit_override/actions)
4
+ [![Gem](https://img.shields.io/gem/v/rails-explicit_override.svg)](https://rubygems.org/gems/rails-explicit_override)
5
+
6
+ Rails has many built-in methods that can be overridden by user code to change behavior. For example if you override `ActionController::action_methods`, you can change which methods are considered routing actions. However, overriding built-in methods can be accidental if you do not realize it exists in the first place. This gem solves that problem by requiring you to explicitly declare which methods you are overriding. If you forget to declare an override, or if you declare an override for a method that does not exist, an error will be raised.
7
+
8
+ Take the example of the `ActionController::action_methods` method. If you want to override it, you would do the following:
9
+
10
+ ```ruby
11
+ class HomeController < ApplicationController
12
+ explicit_overrides!(Rails.env.development?)
13
+
14
+ def index
15
+ # ...
16
+ end
17
+
18
+ private
19
+
20
+ explicit_override
21
+ def action_methods
22
+ # ...
23
+ end
24
+ end
25
+ ```
26
+
27
+ If you forgot to declare the explicit override, you would get the following error:
28
+
29
+ ```
30
+ HomeController is marked as requiring explicit overrides, and already has a
31
+ method named 'action_methods' defined. To override this method, you must call
32
+ 'explicit_override' on the line before the method definition.
33
+ ```
34
+
35
+ ## API
36
+
37
+ There are two main methods you interact with in this gem. The first is:
38
+
39
+ ```ruby
40
+ Rails::ExplicitOverride::ClassMethods#explicit_overrides!(development = false)
41
+ ```
42
+
43
+ This method is used to enable tracking explicit overrides for a class. This module is automatically extended into `ActiveRecord::Base` and `ActionController::Base`, so you can call it in any subclass of those classes. Otherwise you must explicitly extend it into your class. The `development` parameter controls whether or not it will raise, and for best-practice it is expected to only be enabled in development environments to avoid raising errors in production. Once this method is called, any method that is defined that overrides a superclass method must be marked with:
44
+
45
+ ```ruby
46
+ Rails::ExplicitOverride#explicit_override
47
+ ```
48
+
49
+ which must be placed on the line immediately before the method definition. If a method is overridden without being marked, or if a method is marked but does not override a superclass method, an error will be raised.
50
+
51
+ ## Installation
52
+
53
+ Add this line to your application's Gemfile:
54
+
55
+ ```ruby
56
+ gem "rails-explicit_override"
57
+ ```
58
+
59
+ And then execute:
60
+
61
+ $ bundle
62
+
63
+ Or install it yourself as:
64
+
65
+ $ gem install rails-explicit_override
66
+
67
+ ## Contributing
68
+
69
+ Bug reports and pull requests are welcome on GitHub at https://github.com/kddnewton/rails-explicit_override.
70
+
71
+ ## License
72
+
73
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ class ExplicitOverride < Module
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "action_controller"
5
+ require "rails/explicit_override/version"
6
+
7
+ module Rails
8
+ class ExplicitOverride < Module
9
+ class Error < StandardError
10
+ end
11
+
12
+ class MissingExplicitOverrideError < Error
13
+ def initialize(cls, name)
14
+ super(<<~MSG)
15
+ #{cls.name || cls.inspect} is marked as requiring explicit overrides,
16
+ and already has a method named '#{name}' defined. To override this
17
+ method, you must call 'explicit_override' on the line before the
18
+ method definition.
19
+ MSG
20
+ end
21
+ end
22
+
23
+ class UnexpectedExplicitOverrideError < Error
24
+ def initialize(cls, name)
25
+ super(<<~MSG)
26
+ #{cls.name || cls.inspect} is marked as requiring explicit overrides,
27
+ but '#{name}' is not defined in the superclass, so this call to
28
+ 'explicit_override' is unexpected.
29
+ MSG
30
+ end
31
+ end
32
+
33
+ def initialize(method_names)
34
+ explicit_override_lineno = nil
35
+
36
+ define_method(:explicit_override) do
37
+ explicit_override_lineno = caller_locations(1, 1).first.lineno
38
+ end
39
+
40
+ define_method(:method_added) do |name|
41
+ explicit_override = false
42
+ if explicit_override_lineno
43
+ explicit_override = (caller_locations(1, 1).first.lineno - explicit_override_lineno) <= 1
44
+ explicit_override_lineno = nil
45
+ end
46
+
47
+ if explicit_override != (method_defined = method_names.include?(name))
48
+ error = method_defined ? MissingExplicitOverrideError : UnexpectedExplicitOverrideError
49
+ raise error.new(self, name)
50
+ end
51
+
52
+ super(name)
53
+ end
54
+ end
55
+
56
+ module ClassMethods
57
+ # Provides the same interface as Rails::ExplicitOverride, but does
58
+ # nothing. This is meant to be used in non-development environments to
59
+ # avoid both the overhead of tracking method definitions and the risk of
60
+ # raising errors.
61
+ module Noop
62
+ def explicit_override; end
63
+ end
64
+
65
+ private_constant :Noop
66
+
67
+ # Track method definitions to see if they override methods defined in any
68
+ # superclass. If they do, require that they be marked with
69
+ # `explicit_override`. If they are not marked or are marked incorrectly,
70
+ # raise an error.
71
+ def explicit_overrides!(development = false)
72
+ extend(development ? ExplicitOverride.new(instance_methods) : Noop)
73
+ end
74
+
75
+ ActiveRecord::Base.extend(self)
76
+ ActionController::Base.extend(self)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "rails/explicit_override/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "rails-explicit_override"
9
+ spec.version = Rails::ExplicitOverride::VERSION
10
+ spec.authors = ["Kevin Newton"]
11
+ spec.email = ["kddnewton@gmail.com"]
12
+
13
+ spec.summary = "Explicitly mark Rails methods as overridden"
14
+ spec.homepage = "https://github.com/kddnewton/rails-explicit_override"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = %w[
18
+ LICENSE
19
+ README.md
20
+ lib/rails/explicit_override.rb
21
+ lib/rails/explicit_override/version.rb
22
+ rails-explicit_override.gemspec
23
+ ]
24
+
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.metadata = { "rubygems_mfa_required" => "true" }
30
+
31
+ spec.add_dependency "activerecord"
32
+ spec.add_dependency "actionpack"
33
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-explicit_override
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Newton
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2026-02-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: actionpack
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email:
43
+ - kddnewton@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE
49
+ - README.md
50
+ - lib/rails/explicit_override.rb
51
+ - lib/rails/explicit_override/version.rb
52
+ - rails-explicit_override.gemspec
53
+ homepage: https://github.com/kddnewton/rails-explicit_override
54
+ licenses:
55
+ - MIT
56
+ metadata:
57
+ rubygems_mfa_required: 'true'
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubygems_version: 3.5.16
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: Explicitly mark Rails methods as overridden
77
+ test_files: []