-
-
Notifications
You must be signed in to change notification settings - Fork 266
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
216 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Rails | ||
# It is convenient to follow a convention when naming database columns. | ||
# For calendar-type columns, a reasonable convention is: | ||
# | ||
# date => * _on | ||
# datetime => *_at (e.g. timestamps) | ||
# time => *_time | ||
# | ||
# @example | ||
# # bad | ||
# t.date "started_at" | ||
# t.datetime "created_datetime" | ||
# t.time "end_at" | ||
# | ||
# # good | ||
# t.date "started_on" | ||
# t.datetime "created_at" | ||
# t.time "end_time" | ||
# | ||
# "Inspired" by https://github.com/thoughtbot/guides/tree/master/rails | ||
class CalendarTypeSuffix < Cop | ||
MSG = 'Columns of type `%<type>s` should be named with a `%<suffix>s` suffix.' | ||
|
||
def_node_matcher :calendar_type?, '(send _ ${:date :datetime :time} (str $_) ...)' | ||
|
||
def on_send(node) | ||
calendar_type?(node) do |type, name| | ||
unless follows_convention?(type, name) | ||
add_offense( | ||
node, | ||
location: highlight_range(node), | ||
message: format(MSG, type: type, suffix: suffix_for(type)) | ||
) | ||
end | ||
end | ||
end | ||
|
||
def relevant_file?(file) | ||
schema_file?(file) && super | ||
end | ||
|
||
private | ||
|
||
def schema_file?(file) | ||
File.basename(file) == 'schema.rb' | ||
end | ||
|
||
def follows_convention?(type, name) | ||
name.end_with?("_#{suffix_for(type)}") | ||
end | ||
|
||
def suffix_for(type) | ||
case type | ||
when :date then cop_config['DateSuffix'] | ||
when :datetime then cop_config['DateTimeSuffix'] | ||
when :time then cop_config['TimeSuffix'] | ||
end | ||
end | ||
|
||
def highlight_range(node) | ||
node.loc.expression.with( | ||
end_pos: node.children[2].loc.expression.end_pos | ||
) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Rails::CalendarTypeSuffix, :config do | ||
subject(:cop) do | ||
cop = described_class.new(config) | ||
allow(cop).to receive(:relevant_file?).and_return(true) | ||
cop | ||
end | ||
|
||
let(:schema_path) do | ||
f = Tempfile.create('rubocop-rails-CalendarTypeSuffix-test-') | ||
f.close | ||
Pathname(f.path) | ||
end | ||
|
||
let(:cop_config) do | ||
{ | ||
'DateSuffix' => 'on', | ||
'DateTimeSuffix' => 'at', | ||
'TimeSuffix' => 'time' | ||
} | ||
end | ||
|
||
before do | ||
RuboCop::Rails::SchemaLoader.reset! | ||
schema_path.write(schema) | ||
allow(RuboCop::Rails::SchemaLoader).to receive(:db_schema_path) | ||
.and_return(schema_path) | ||
end | ||
|
||
after do | ||
RuboCop::Rails::SchemaLoader.reset! | ||
schema_path.unlink | ||
end | ||
|
||
context 'when calendar type columns do no follow the conventional suffixes' do | ||
let(:schema) { <<~RUBY } | ||
ActiveRecord::Schema.define(version: 2020_02_02_075409) do | ||
create_table "users", force: :cascade do |t| | ||
t.date "sign_up", null: false | ||
t.datetime "last_login" | ||
t.time "lock_until" | ||
end | ||
end | ||
RUBY | ||
|
||
it 'registers an offense' do | ||
expect_offense(<<~RUBY) | ||
ActiveRecord::Schema.define(version: 2020_02_02_075409) do | ||
create_table "users", force: :cascade do |t| | ||
t.date "sign_up", null: false | ||
^^^^^^^^^^^^^^^^ Columns of type `date` should be named with a `on` suffix. | ||
t.datetime "last_login" | ||
^^^^^^^^^^^^^^^^^^^^^^^ Columns of type `datetime` should be named with a `at` suffix. | ||
t.time "lock_until" | ||
^^^^^^^^^^^^^^^^^^^ Columns of type `time` should be named with a `time` suffix. | ||
end | ||
end | ||
RUBY | ||
end | ||
end | ||
|
||
context 'when calendar type columns follow the conventional suffixes' do | ||
let(:schema) { <<~RUBY } | ||
ActiveRecord::Schema.define(version: 2020_02_02_075409) do | ||
create_table "users", force: :cascade do |t| | ||
t.date "signed_up_on", null: false | ||
t.datetime "last_login_at" | ||
t.time "locked_until_time" | ||
end | ||
end | ||
RUBY | ||
|
||
it 'does not register an offense' do | ||
expect_no_offenses(schema) | ||
end | ||
end | ||
end |