Whats the difference between method argument with and without underscore _ in Ruby

Viewed 98

I try to find out the purpose of underscore in method argument but not find any reason. Like there is a method

def eligible(user)
end

and same method but with an underscore in argument

def eligible(_user)
end

whats the difference between them

2 Answers

_ has some meaning as part of the ruby syntax.

Ruby will suppress warnings of unused variables that start with _:

# underscore.rb

def unused_variables_check
  _nowarn = "not used, but warning is suppressed"
  notused = "not used"
  used    = "i need it 100%"
  used
end

# $ ruby -w underscore.rb
# underscore.rb:3: warning: assigned but unused variable - notused

Ruby does not complain about unused arguments:

def unused_arguments_check(a, b)
  p a
end
unused_arguments_check("yay", "nup")

# $ ruby -w underscore.rb
# "yay"

Duplicate argument names is an error:

def dup_arguments_check(a, a) end

# $ ruby -w underscore.rb
# underscore.rb:14: duplicated argument name
# def dup_arguments_check(a, a) end

Unless those names start with an underscore. This is a ruby syntax feature, not just a style guide. It is used on occasion to ignore arguments:

def dup_arguments_with_underscore_check(_a, _a, _, _)
  p _a # don't use it after "ignoring". but, i thought, it would be the last `_a`
  p _
end
dup_arguments_with_underscore_check(:x, :lost_i, :y, :n_limbo)

# $ ruby -w underscore.rb
# :x
# :y

_ has some semantic meaning as part of a style guide. Most common meaning is "this is unused variable/argument".

rubocop is a style checker/formatter. It will complain about everything, including unused arguments.

$ rubocop -l
Inspecting 1 file
W

Offenses:

underscore.rb:3:3: W: Lint/UselessAssignment: Useless assignment to variable - notused.
  notused = "not used"
  ^^^^^^^
underscore.rb:9:31: W: [Correctable] Lint/UnusedMethodArgument: Unused method argument - b. If it's necessary, use _ or _b as an argument name to indicate that it won't be used.
def unused_arguments_check(a, b)
                              ^
underscore.rb:16:45: W: Lint/UnderscorePrefixedVariableName: Do not use prefix _ for a variable that is used.
def dup_arguments_with_underscore_check(_a, _a, _, _)
                                            ^^
underscore.rb:16:52: W: Lint/UnderscorePrefixedVariableName: Do not use prefix _ for a variable that is used.
def dup_arguments_with_underscore_check(_a, _a, _, _)
                                                   ^
#                                               ^
#  Hey, rubocop, I'm using the first `_` -------'

By using _ to match a common style, everyone looking at your code, including future self, will have a bit of extra information.


Ruby convention: https://rubystyle.guide/#underscore-unused-vars

Rubocop convention: https://docs.rubocop.org/rubocop/cops_lint.html#lintunusedmethodargument

Related