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 +7 -0
- data/LICENSE +21 -0
- data/README.md +73 -0
- data/lib/rails/explicit_override/version.rb +7 -0
- data/lib/rails/explicit_override.rb +79 -0
- data/rails-explicit_override.gemspec +33 -0
- metadata +77 -0
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
|
+
[](https://github.com/kddnewton/rails-explicit_override/actions)
|
|
4
|
+
[](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,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: []
|