class RuboCop::Cop::Rails::Date
This cop checks for the correct use of Date
methods, such as Date.today, Date.current etc.
Using `Date.today` is dangerous, because it doesn't know anything about Rails
time zone. You must use `Time.zone.today` instead.
The cop also reports warnings when you are using `to_time` method, because it doesn't know about Rails
time zone either.
Two styles are supported for this cop. When EnforcedStyle is 'strict' then the Date
methods `today`, `current`, `yesterday`, and `tomorrow` are prohibited and the usage of both `to_time` and 'to_time_in_current_zone' are reported as warning.
When EnforcedStyle is 'flexible' then only `Date.today` is prohibited and only `to_time` is reported as warning.
@example EnforcedStyle: strict
# bad Date.current Date.yesterday Date.today date.to_time # good Time.zone.today Time.zone.today - 1.day
@example EnforcedStyle: flexible (default)
# bad Date.today date.to_time # good Time.zone.today Time.zone.today - 1.day Date.current Date.yesterday date.in_time_zone
Constants
- BAD_DAYS
- DEPRECATED_METHODS
- DEPRECATED_MSG
- MSG
- MSG_SEND
Public Instance Methods
# File lib/rubocop/cop/rails/date.rb, line 64 def on_const(node) mod, klass = *node.children # we should only check core Date class (`Date` or `::Date`) return unless (mod.nil? || mod.cbase_type?) && method_send?(node) check_date_node(node.parent) if klass == :Date end
# File lib/rubocop/cop/rails/date.rb, line 72 def on_send(node) return unless node.receiver && bad_methods.include?(node.method_name) return if safe_chain?(node) || safe_to_time?(node) check_deprecated_methods(node) add_offense(node, location: :selector, message: format(MSG_SEND, method: node.method_name)) end
Private Instance Methods
# File lib/rubocop/cop/rails/date.rb, line 147 def bad_days BAD_DAYS - good_days end
# File lib/rubocop/cop/rails/date.rb, line 151 def bad_methods %i[to_time to_time_in_current_zone] end
# File lib/rubocop/cop/rails/date.rb, line 97 def check_date_node(node) chain = extract_method_chain(node) return if (chain & bad_days).empty? method_name = (chain & bad_days).join('.') day = method_name day = 'today' if method_name == 'current' add_offense(node, location: :selector, message: format(MSG, method_called: method_name, day: day)) end
# File lib/rubocop/cop/rails/date.rb, line 86 def check_deprecated_methods(node) DEPRECATED_METHODS.each do |relevant:, deprecated:| next unless node.method_name == deprecated.to_sym add_offense(node, location: :selector, message: format(DEPRECATED_MSG, deprecated: deprecated, relevant: relevant)) end end
# File lib/rubocop/cop/rails/date.rb, line 113 def extract_method_chain(node) [node, *node.each_ancestor(:send)].map(&:method_name) end
# File lib/rubocop/cop/rails/date.rb, line 143 def good_days style == :strict ? [] : %i[current yesterday tomorrow] end
# File lib/rubocop/cop/rails/date.rb, line 155 def good_methods style == :strict ? [] : TimeZone::ACCEPTED_METHODS end
checks that parent node of send_type and receiver is the given node
# File lib/rubocop/cop/rails/date.rb, line 119 def method_send?(node) return false unless node.parent&.send_type? node.parent.receiver == node end
# File lib/rubocop/cop/rails/date.rb, line 125 def safe_chain?(node) chain = extract_method_chain(node) (chain & bad_methods).empty? || !(chain & good_methods).empty? end
# File lib/rubocop/cop/rails/date.rb, line 131 def safe_to_time?(node) return unless node.method?(:to_time) if node.receiver.str_type? zone_regexp = /([+-][\d:]+|\dZ)\z/ node.receiver.str_content.match(zone_regexp) else node.arguments.one? end end