Naming Conventions in Ruby
From Logic Wiki
Source Codes Layout
- 2 space indent no tabs
- Use Unix-style line endings
- Don't use ; to separate statements and expressions. As a corollary - use one expression per line
- Prefer a single-line format for class definitions with no body
- Avoid single-line methods. (exception : empty-body methods.)
- Use spaces around operators, after commas, colons and semicolons, around { and before }.
- No spaces after (, [ or before ], )
- No space after !
- No space inside range literals.
- Indent when as deep as case.
case when song.name == 'Misty' puts 'Not again!' when song.duration > 120 puts 'Too long!' when Time.now.hour > 21 puts "It's too late" else song.play end
- Use empty lines between method definitions and also to break up methods into logical paragraphs internally
- Avoid comma after the last parameter in a method call, especially when the parameters are not on separate lines
- Use spaces around the = operator when assigning default values to method parameters
- Avoid line continuation \ where not required.
- Align the parameters of a method call if they span more than one line. When aligning parameters is not appropriate due to line-length constraints, single indent for the lines after the first is also acceptable
# bad (double indent)
def send_mail(source)
Mailer.deliver(
to: 'bob@example.com',
from: 'us@example.com',
subject: 'Important message',
body: source.text)
end
# good
def send_mail(source)
Mailer.deliver(to: 'bob@example.com',
from: 'us@example.com',
subject: 'Important message',
body: source.text)
end
# good (normal indent)
def send_mail(source)
Mailer.deliver(
to: 'bob@example.com',
from: 'us@example.com',
subject: 'Important message',
body: source.text
)
end
- Add underscores to large numeric literals to improve their readability
num = 1_000_000
- Limit lines to 80 characters
Syntax
- Use def with parentheses when there are parameters. Omit the parentheses when the method doesn't accept any parameters
- Do not use for, unless you know exactly why. Most of the time iterators should be used instead. for is implemented in terms of each (so you're adding a level of indirection), but with a twist - for doesn't introduce a new scope (unlike each) and variables defined in its block will be visible outside it
- Do not use then for multi-line if/unless
- Favor the ternary operator(?:) over if/then/else/end constructs.
- Use one expression per branch in a ternary operator. This also means that ternary operators must not be nested
- Leverage the fact that if and case are expressions which return a result.
# bad
if condition
result = x
else
result = y
end
# good
result =
if condition
x
else
y
end
- Use ! instead of not
- The and and or keywords are banned. It's just not worth it. Always use && and || instead
- Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||
# bad if some_condition do_something end # good do_something if some_condition # another good option some_condition && do_something
- Do not use unless with else. Rewrite these with the positive case first.
- Don't use parentheses around the condition of an if/unless/while/until
- Avoid return where not required for flow of control.
- Avoid self where not required. (It is only required when calling a self write accessor.)
- Use ||= to initialize variables only if they're not already initialized
# bad name = name ? name : 'Bozhidar' # bad name = 'Bozhidar' unless name # good - set name to Bozhidar, only if it's nil or false name ||= 'Bozhidar'
- Use the new lambda literal syntax for single line body blocks. Use the lambda method for multi-line blocks
# bad
l = lambda { |a, b| a + b }
l.call(1, 2)
# correct, but looks extremely awkward
l = ->(a, b) do
tmp = a * 7
tmp * b / 50
end
# good
l = ->(a, b) { a + b }
l.call(1, 2)
l = lambda do |a, b|
tmp = a * 7
tmp * b / 50
end
- Don't omit the parameter parentheses when defining a stabby lambda with parameters.
# bad
l = ->x, y { something(x, y) }
# good
l = ->(x, y) { something(x, y) }
- Prefer proc over Proc.new
# bad
p = Proc.new { |n| puts n }
# good
p = proc { |n| puts n }
- Don't use count as a substitute for size.
Naming
- Name identifiers in English
- Use snake_case for symbols, methods and variables.
- Use CamelCase for classes and modules. (Keep acronyms like HTTP, RFC, XML uppercase.)
- Use snake_case for naming files, e.g. hello_world.rb
- Use snake_case for naming directories, e.g. lib/hello_world/hello_world.rb
- Aim to have just a single class/module per source file. Name the file name as the class/module, but replacing CamelCase with snake_case.
- Use SCREAMING_SNAKE_CASE for other constants.
Comments
- If multiple lines are required to describe the problem, subsequent lines should be indented three spaces after the # (one general plus two for indentation purpose
- Use TODO to note missing features or functionality that should be added at a later date.
- Use FIXME to note broken code that needs to be fixed.
- Use OPTIMIZE to note slow or inefficient code that may cause performance problems.
- Use HACK to note code smells where questionable coding practices were used and should be refactored away.
- Use REVIEW to note anything that should be looked at to confirm it is working as intended. For example: REVIEW: Are we sure this is how the client does X currently?
- Use other custom annotation keywords if it feels appropriate, but be sure to document them in your project's README or similar.
Classes & Modules
- Use a consistent structure in your class definitions
class Person # extend and include go first extend SomeModule include AnotherModule # inner classes CustomErrorKlass = Class.new(StandardError) # constants are next SOME_CONSTANT = 20 # afterwards we have attribute macros attr_reader :name # followed by other macros (if any) validates :name # public class methods are next in line def self.some_method end # initialization goes between class methods and other instance methods def initialize end # followed by other public instance methods def some_method end # protected and private methods are grouped near the end protected def some_protected_method end private def some_private_method end end
- Don't nest multi line classes within classes. Try to have such nested classes each in their own file in a folder named like the containing class
# bad
# foo.rb
class Foo
class Bar
# 30 methods inside
end
class Car
# 20 methods inside
end
# 30 methods inside
end
# good
# foo.rb
class Foo
# 30 methods inside
end
# foo/bar.rb
class Foo
class Bar
# 30 methods inside
end
end
# foo/car.rb
class Foo
class Car
# 20 methods inside
end
end
- Prefer modules to classes with only class methods. Classes should be used only when it makes sense to create instances out of them