class RuboCop::Cop::Style::GuardClause

Use a guard clause instead of wrapping the code inside a conditional expression

@example

# bad
def test
  if something
    work
  end
end

# good
def test
  return unless something
  work
end

# also good
def test
  work if something
end

# bad
if something
  raise 'exception'
else
  ok
end

# good
raise 'exception' if something
ok

Constants

MSG

Public Instance Methods

on_def(node) click to toggle source
# File lib/rubocop/cop/style/guard_clause.rb, line 50
def on_def(node)
  _, _, body = *node
  return unless body

  if if?(body)
    check_trailing_if(body)
  elsif body.begin_type?
    last_expr = body.children.last
    check_trailing_if(last_expr) if if?(last_expr)
  end
end
on_if(node) click to toggle source
# File lib/rubocop/cop/style/guard_clause.rb, line 62
def on_if(node)
  cond, body, else_body = *node

  return unless body && else_body
  # discard modifier ifs and ternary_ops
  return if modifier_if?(node) || ternary_op?(node) || elsif?(node)

  return unless single_line_control_flow_exit?(body) ||
                single_line_control_flow_exit?(else_body)
  return if cond.multiline?
  return if line_too_long_when_corrected?(node)

  add_offense(node, :keyword, MSG)
end

Private Instance Methods

check_trailing_if(node) click to toggle source
# File lib/rubocop/cop/style/guard_clause.rb, line 89
def check_trailing_if(node)
  cond, body, else_body = *node

  return if body && else_body
  # discard modifier ifs and ternary_ops
  return if modifier_if?(node) || ternary_op?(node)
  return if cond.multiline?
  # discard short ifs
  return unless min_body_length?(node)
  return if line_too_long_when_corrected?(node)

  add_offense(node, :keyword, MSG)
end
elsif?(node) click to toggle source
# File lib/rubocop/cop/style/guard_clause.rb, line 83
def elsif?(node)
  return false unless node.parent && node.parent.if_type?
  _condition, _if_branch, else_branch = *node.parent
  else_branch.equal?(node)
end
if?(node) click to toggle source
# File lib/rubocop/cop/style/guard_clause.rb, line 79
def if?(node)
  node && node.if_type?
end
line_too_long?(node, body, keyword, condition) click to toggle source
# File lib/rubocop/cop/style/guard_clause.rb, line 113
def line_too_long?(node, body, keyword, condition)
  max    = config.for_cop('Metrics/LineLength')['Max'] || 80
  indent = node.loc.column
  source = body && body.source || ''
  # 2 is for spaces on left and right of keyword
  indent + (source + keyword + condition.source).length + 2 > max
end
line_too_long_when_corrected?(node) click to toggle source
# File lib/rubocop/cop/style/guard_clause.rb, line 103
def line_too_long_when_corrected?(node)
  cond, body, else_body = *node

  if single_line_control_flow_exit?(body) || !else_body
    line_too_long?(node, body, 'if', cond)
  else
    line_too_long?(node, else_body, 'unless', cond)
  end
end