I see in ruby classes some people using _
prefix to define instance variables like @_property
while in normal condition attr_writer
uses the normal name like @property
to define instance variables.
What is the point of doing this and what is the difference?
CodePudding user response:
The _
prefix isn't a language feature, it doesn't do anything special, it is just a convention.
In most cases, the developer wants to indicate that a variable is not in use, for example, a block variable that is not used in a block. Or they want to indicate that the variable is an internal variable of a module or gem and that others should not read or modify this variable directly.
CodePudding user response:
There are 2 possible answers here depending on type of a variable.
Instance variable
When _
is used to prefix an instances variable (like in your question) it is usually just a convention to make it clear that that instance variable is private implementation detail and should not be used outside of the current scope. You might encounter it especially in modules which are to be included in some other classes - in which case the instance variable is defined and used by that module, but it belongs and is scoped to the object itself. I personally prefer object-scoped registries for this, but "private" instance variable is a quick, dirty and popular way to go. Alos, prefixing instance variable name with _
reduces chances of name conflict.
# Library code
module SomeExternalLibraryModule
def foo
@_something ||= SomeExternalLibraryModule::Something.new(self)
end
end
# Application code
class User
include SomeExternalLibraryModule
attr_reader :something # name conflict "avoided"! Phew!
def bar
@_something.do_sth
# "_" means - you'd better know what you're doing here!
# There is no guarantee that instance variable will be present in the future release
end
end
Local variable
When local variable is prefixed with _
this means that that variable is not being used in the code. It is especially useful when using iterators, or consuming other multi-element inputs of which you're interested in only one.
It is quite common to see just _
as a variable name. It has a bit of a special meaning for parser, which is you explicitly saying "I do not care what that is". As such, it is the only argument name that is allowed multiple time in a single definition:
def foo(_, _, a)
a
end
foo(1,2,3) #=> 3
def bar(a,a,b); end #=> SyntaxError
However, this is usually the best practice to use "I do not care" with a name, which will make your life easier in the future if you actually decide that you need to use other arguments:
def foo(_name, _html_options, options)
options.delete(:some_option)
super
end