Commit 45568bed authored by Lin Jen-Shin's avatar Lin Jen-Shin

Updates based on feedback

parent ffec300b
...@@ -12,6 +12,7 @@ module Spammable ...@@ -12,6 +12,7 @@ module Spammable
attr_accessor :spam attr_accessor :spam
attr_accessor :spam_log attr_accessor :spam_log
alias_method :spam?, :spam
after_validation :check_for_spam, on: [:create, :update] after_validation :check_for_spam, on: [:create, :update]
...@@ -34,10 +35,6 @@ module Spammable ...@@ -34,10 +35,6 @@ module Spammable
end end
end end
def spam?
spam
end
def check_for_spam def check_for_spam
error_msg = if Gitlab::Recaptcha.enabled? error_msg = if Gitlab::Recaptcha.enabled?
"Your #{spammable_entity_type} has been recognized as spam. "\ "Your #{spammable_entity_type} has been recognized as spam. "\
......
...@@ -36,6 +36,7 @@ comments: false ...@@ -36,6 +36,7 @@ comments: false
- [`Gemfile` guidelines](gemfile.md) - [`Gemfile` guidelines](gemfile.md)
- [Sidekiq debugging](sidekiq_debugging.md) - [Sidekiq debugging](sidekiq_debugging.md)
- [Gotchas](gotchas.md) to avoid - [Gotchas](gotchas.md) to avoid
- [Avoid modules with instance variables](module_with_instance_variables.md) if possible
- [Issue and merge requests state models](object_state_models.md) - [Issue and merge requests state models](object_state_models.md)
- [How to dump production data to staging](db_dump.md) - [How to dump production data to staging](db_dump.md)
- [Working with the GitHub importer](github_importer.md) - [Working with the GitHub importer](github_importer.md)
......
...@@ -55,10 +55,9 @@ they communicate in a clear way, rather than implicit dependencies. ...@@ -55,10 +55,9 @@ they communicate in a clear way, rather than implicit dependencies.
### Acceptable use ### Acceptable use
However, it's not all that bad when using instance variables in a module, However, it's not always bad to use instance variables in a module,
as long as it's contained in the same module, that is no other modules or as long as it's contained in the same module; that is, no other modules or
objects are touching them. If that's the case, then it would be an acceptable objects are touching them, then it would be an acceptable use.
use.
We especially allow the case where a single instance variable is used with We especially allow the case where a single instance variable is used with
`||=` to setup the value. This would look like: `||=` to setup the value. This would look like:
...@@ -93,7 +92,7 @@ module Gitlab ...@@ -93,7 +92,7 @@ module Gitlab
end end
``` ```
It's still offending because it's not just `||=`, but We could split this It's still offending because it's not just `||=`, but we could split this
method into two: method into two:
``` ruby ``` ruby
...@@ -135,7 +134,7 @@ end ...@@ -135,7 +134,7 @@ end
``` ```
There are several implicit dependencies here. First, `params` should be There are several implicit dependencies here. First, `params` should be
defined before using. Second, `filter_spam_check_params` should be called defined before use. Second, `filter_spam_check_params` should be called
before `spam_check`. These are all implicit and the includer could be using before `spam_check`. These are all implicit and the includer could be using
those instance variables without awareness. those instance variables without awareness.
...@@ -175,18 +174,18 @@ end ...@@ -175,18 +174,18 @@ end
``` ```
This way, all those instance variables are isolated in `SpamCheckService` This way, all those instance variables are isolated in `SpamCheckService`
rather than who ever include the module, and those modules which were also rather than whatever includes the module, and those modules which were also
included, making it much easier to track down the issues if there's any, included, making it much easier to track down any issues,
and it also reduces the chance of having name conflicts. and reducing the chance of having name conflicts.
### Things we might need to ignore right now ### Things we might need to ignore right now
Since the way how Rails helpers and mailers work, we might not be able to Because of the way Rails helpers and mailers work, we might not be able to
avoid the use of instance variables there. For those cases, we could ignore avoid the use of instance variables there. For those cases, we could ignore
them at the moment. At least we're not going to share those modules with them at the moment. At least we're not going to share those modules with
other random objects, so they're still somehow isolated. other random objects, so they're still somewhat isolated.
### Instance variables in the views ### Instance variables in views
They're terrible, because they're also shared between different controllers, They're terrible, because they're also shared between different controllers,
and it's very hard to track where those instance variables were set when we and it's very hard to track where those instance variables were set when we
...@@ -210,5 +209,5 @@ And in the partial: ...@@ -210,5 +209,5 @@ And in the partial:
- project = local_assigns.fetch(:project) - project = local_assigns.fetch(:project)
``` ```
This way it's very clear where those values were coming from. In the future, This way it's clearer where those values were coming from. In the future,
we should also forbid the use of instance variables in partials. we should also forbid the use of instance variables in partials.
...@@ -42,11 +42,11 @@ module StdoutReporterWithScenarioLocation ...@@ -42,11 +42,11 @@ module StdoutReporterWithScenarioLocation
# Override the standard reporter to show filename and line number next to each # Override the standard reporter to show filename and line number next to each
# scenario for easy, focused re-runs # scenario for easy, focused re-runs
def before_scenario_run(scenario, step_definitions = nil) def before_scenario_run(scenario, step_definitions = nil)
max_step_name_length = scenario.steps.map(&:name).map(&:length).max if scenario.steps.any? @max_step_name_length = scenario.steps.map(&:name).map(&:length).max if scenario.steps.any? # rubocop:disable Cop/ModuleWithInstanceVariables
name = scenario.name name = scenario.name
# This number has no significance, it's just to line things up # This number has no significance, it's just to line things up
max_length = max_step_name_length + 19 max_length = @max_step_name_length + 19 # rubocop:disable Cop/ModuleWithInstanceVariables
out.puts "\n #{'Scenario:'.green} #{name.light_green.ljust(max_length)}" \ out.puts "\n #{'Scenario:'.green} #{name.light_green.ljust(max_length)}" \
" # #{scenario.feature.filename}:#{scenario.line}" " # #{scenario.feature.filename}:#{scenario.line}"
end end
......
...@@ -59,13 +59,13 @@ module Gitlab ...@@ -59,13 +59,13 @@ module Gitlab
def helpers(*nodes) def helpers(*nodes)
nodes.each do |symbol| nodes.each do |symbol|
define_method("#{symbol}_defined?") do define_method("#{symbol}_defined?") do
@entries[symbol]&.specified? entries[symbol]&.specified?
end end
define_method("#{symbol}_value") do define_method("#{symbol}_value") do
return unless @entries[symbol] && @entries[symbol].valid? return unless entries[symbol] && entries[symbol].valid?
@entries[symbol].value entries[symbol].value
end end
end end
end end
......
...@@ -5,7 +5,7 @@ module RuboCop ...@@ -5,7 +5,7 @@ module RuboCop
Do not use instance variables in a module. Please read this Do not use instance variables in a module. Please read this
for the rationale behind it: for the rationale behind it:
doc/development/module_with_instance_variables.md https://docs.gitlab.com/ee/development/module_with_instance_variables.html
If you think the use for this is fine, please just add: If you think the use for this is fine, please just add:
# rubocop:disable Cop/ModuleWithInstanceVariables # rubocop:disable Cop/ModuleWithInstanceVariables
...@@ -56,9 +56,7 @@ module RuboCop ...@@ -56,9 +56,7 @@ module RuboCop
add_offense(offense, :expression) add_offense(offense, :expression)
end end
# We allow initialize method and single ivar # We allow initialize method and single ivar
elsif initialize_method?(definition) || single_ivar?(definition) elsif !initialize_method?(definition) && !single_ivar?(definition)
next
else
definition.each_descendant(:ivar, :ivasgn) do |offense| definition.each_descendant(:ivar, :ivasgn) do |offense|
add_offense(offense, :expression) add_offense(offense, :expression)
end end
......
...@@ -8,7 +8,9 @@ describe RuboCop::Cop::ModuleWithInstanceVariables do ...@@ -8,7 +8,9 @@ describe RuboCop::Cop::ModuleWithInstanceVariables do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
shared_examples('registering offense') do shared_examples('registering offense') do |options|
let(:offending_lines) { options[:offending_lines] }
it 'registers an offense when instance variable is used in a module' do it 'registers an offense when instance variable is used in a module' do
inspect_source(cop, source) inspect_source(cop, source)
...@@ -28,63 +30,57 @@ describe RuboCop::Cop::ModuleWithInstanceVariables do ...@@ -28,63 +30,57 @@ describe RuboCop::Cop::ModuleWithInstanceVariables do
end end
context 'when source is a regular module' do context 'when source is a regular module' do
let(:source) do it_behaves_like 'registering offense', offending_lines: [3] do
<<~RUBY let(:source) do
module M <<~RUBY
def f module M
@f = true def f
@f = true
end
end end
end RUBY
RUBY end
end end
let(:offending_lines) { [3] }
it_behaves_like 'registering offense'
end end
context 'when source is a nested module' do context 'when source is a nested module' do
let(:source) do it_behaves_like 'registering offense', offending_lines: [4] do
<<~RUBY let(:source) do
module N <<~RUBY
module M module N
def f module M
@f = true def f
@f = true
end
end end
end end
end RUBY
RUBY end
end end
let(:offending_lines) { [4] }
it_behaves_like 'registering offense'
end end
context 'when source is a nested module with multiple offenses' do context 'when source is a nested module with multiple offenses' do
let(:source) do it_behaves_like 'registering offense', offending_lines: [4, 12] do
<<~RUBY let(:source) do
module N <<~RUBY
module M module N
def f module M
@f = true def f
end @f = true
end
def g
true def g
end true
end
def h
@h = true def h
@h = true
end
end end
end end
end RUBY
RUBY end
end end
let(:offending_lines) { [4, 12] }
it_behaves_like 'registering offense'
end end
context 'with regular ivar assignment' do context 'with regular ivar assignment' do
...@@ -124,78 +120,74 @@ describe RuboCop::Cop::ModuleWithInstanceVariables do ...@@ -124,78 +120,74 @@ describe RuboCop::Cop::ModuleWithInstanceVariables do
end end
context 'when source is using simple or ivar assignment' do context 'when source is using simple or ivar assignment' do
let(:source) do it_behaves_like 'not registering offense' do
<<~RUBY let(:source) do
module M <<~RUBY
def f module M
@f ||= true def f
@f ||= true
end
end end
end RUBY
RUBY end
end end
it_behaves_like 'not registering offense'
end end
context 'when source is using simple ivar' do context 'when source is using simple ivar' do
let(:source) do it_behaves_like 'not registering offense' do
<<~RUBY let(:source) do
module M <<~RUBY
def f? module M
@f def f?
@f
end
end end
end RUBY
RUBY end
end end
it_behaves_like 'not registering offense'
end end
context 'when source is defining initialize' do context 'when source is defining initialize' do
let(:source) do it_behaves_like 'not registering offense' do
<<~RUBY let(:source) do
module M <<~RUBY
def initialize module M
@a = 1 def initialize
@b = 2 @a = 1
@b = 2
end
end end
end RUBY
RUBY end
end end
it_behaves_like 'not registering offense'
end end
context 'when source is using simple or ivar assignment with other ivar' do context 'when source is using simple or ivar assignment with other ivar' do
let(:source) do it_behaves_like 'registering offense', offending_lines: [3] do
<<~RUBY let(:source) do
module M <<~RUBY
def f module M
@f ||= g(@g) def f
@f ||= g(@g)
end
end end
end RUBY
RUBY end
end end
let(:offending_lines) { [3] }
it_behaves_like 'registering offense'
end end
context 'when source is using or ivar assignment with something else' do context 'when source is using or ivar assignment with something else' do
let(:source) do it_behaves_like 'registering offense', offending_lines: [3, 4] do
<<~RUBY let(:source) do
module M <<~RUBY
def f module M
@f ||= true def f
@f.to_s @f ||= true
@f.to_s
end
end end
end RUBY
RUBY end
end end
let(:offending_lines) { [3, 4] }
it_behaves_like 'registering offense'
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment