Class: RuboCop::Cop::Rails::DurationArithmetic

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Defined in:
lib/rubocop/cop/rails/duration_arithmetic.rb

Overview

Checks if a duration is added to or subtracted from ‘Time.current`.

Examples:

# bad
Time.current - 1.minute
Time.current + 2.days

# good - using relative would make it harder to express and read
Date.yesterday + 3.days
created_at - 1.minute
3.days - 1.hour

# good
1.minute.ago
2.days.from_now

Constant Summary collapse

MSG =
'Do not add or subtract duration.'
RESTRICT_ON_SEND =
%i[+ -].freeze
DURATIONS =
Set[:second, :seconds, :minute, :minutes, :hour, :hours,
:day, :days, :week, :weeks, :fortnight, :fortnights,
:month, :months, :year, :years]

Instance Method Summary collapse

Instance Method Details

#duration?(node) ⇒ Boolean

Match a literal Duration

Examples:

source that matches

1.hour

source that matches

9.5.weeks

Parameters:

  • node (RuboCop::AST::Node)

Returns:

  • (Boolean)

    true if matches



58
# File 'lib/rubocop/cop/rails/duration_arithmetic.rb', line 58

def_node_matcher :duration?, '(send { int float (send nil _) } DURATIONS)'

#duration_arithmetic_argument?(node) { ... } ⇒ Object

Match duration subtraction or addition with current time.

Examples:

source that matches

Time.current - 1.hour

source that matches

::Time.zone.now + 1.hour

Parameters:

  • node (RuboCop::AST::Node)

Yields:

  • operator and duration



43
44
45
# File 'lib/rubocop/cop/rails/duration_arithmetic.rb', line 43

def_node_matcher :duration_arithmetic_argument?, <<~PATTERN
  (send #time_current? ${ :+ :- } $#duration?)
PATTERN

#on_send(node) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/rubocop/cop/rails/duration_arithmetic.rb', line 78

def on_send(node)
  duration_arithmetic_argument?(node) do |*operation|
    add_offense(node) do |corrector|
      corrector.replace(node, corrected_source(*operation))
    end
  end
end

#time_current?(node) ⇒ Boolean

Match Time.current

Examples:

source that matches

Time.current

source that matches

::Time.zone.now

Parameters:

  • node (RuboCop::AST::Node)

Returns:

  • (Boolean)

    true if matches



71
72
73
74
75
76
# File 'lib/rubocop/cop/rails/duration_arithmetic.rb', line 71

def_node_matcher :time_current?, <<~PATTERN
  {
    (send (const {nil? cbase} :Time) :current)
    (send (send (const {nil? cbase} :Time) :zone) :now)
  }
PATTERN