diff --git a/Dockerfile b/Dockerfile index 24ab906e..296933b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,18 @@ -FROM ruby:2.3-alpine +FROM ruby:2.4-alpine WORKDIR /usr/src/app -COPY Gemfile /usr/src/app/ -COPY Gemfile.lock /usr/src/app/ -RUN gem install bundler && \ - bundle install -j 4 && \ - rm -fr /usr/share/ri +RUN adduser -u 9000 -D app -RUN apk --update add git +COPY Gemfile Gemfile.lock /usr/src/app/ + +RUN gem install bundler && \ + bundle install -j 4 --without=test && \ + chown -R app:app /usr/local/bundle && \ + rm -fr ~/.gem ~/.bundle ~/.wh..gem -RUN adduser -u 9000 -D app COPY . /usr/src/app -RUN chown -R app:app /usr/src/app +RUN chown -R app:app . USER app diff --git a/Gemfile b/Gemfile index 506fbd37..9962c74c 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,7 @@ source 'https://rubygems.org' gem "activesupport", require: false gem "parser", "~> 2.4.0" gem "pry", require: false -gem "rubocop", "~> 0.45", require: false +gem "rubocop", "~> 0.50.0", require: false gem "rubocop-migrations", require: false gem "rubocop-rspec", require: false gem "safe_yaml" diff --git a/Gemfile.lock b/Gemfile.lock index e961e2c5..864515a9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,57 +1,58 @@ GEM remote: https://rubygems.org/ specs: - activesupport (5.0.1) + activesupport (5.1.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (~> 0.7) minitest (~> 5.1) tzinfo (~> 1.1) ast (2.3.0) - coderay (1.1.1) - concurrent-ruby (1.0.3) - diff-lcs (1.2.5) - i18n (0.7.0) - method_source (0.8.2) - minitest (5.10.1) + coderay (1.1.2) + concurrent-ruby (1.0.5) + diff-lcs (1.3) + i18n (0.8.6) + method_source (0.9.0) + minitest (5.10.3) + parallel (1.12.0) parser (2.4.0.0) ast (~> 2.2) powerpack (0.1.1) - pry (0.10.4) + pry (0.11.1) coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - rainbow (2.1.0) - rake (12.0.0) - rspec (3.5.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-core (3.5.4) - rspec-support (~> 3.5.0) - rspec-expectations (3.5.0) + method_source (~> 0.9.0) + rainbow (2.2.2) + rake + rake (12.1.0) + rspec (3.6.0) + rspec-core (~> 3.6.0) + rspec-expectations (~> 3.6.0) + rspec-mocks (~> 3.6.0) + rspec-core (3.6.0) + rspec-support (~> 3.6.0) + rspec-expectations (3.6.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-mocks (3.5.0) + rspec-support (~> 3.6.0) + rspec-mocks (3.6.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-support (3.5.0) - rubocop (0.46.0) - parser (>= 2.3.1.1, < 3.0) + rspec-support (~> 3.6.0) + rspec-support (3.6.0) + rubocop (0.50.0) + parallel (~> 1.10) + parser (>= 2.3.3.1, < 3.0) powerpack (~> 0.1) - rainbow (>= 1.99.1, < 3.0) + rainbow (>= 2.2.2, < 3.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) rubocop-migrations (0.1.2) rubocop (~> 0.41) - rubocop-rspec (1.8.0) - rubocop (>= 0.42.0) - ruby-progressbar (1.8.1) + rubocop-rspec (1.18.0) + rubocop (>= 0.50.0) + ruby-progressbar (1.9.0) safe_yaml (1.0.4) - slop (3.6.0) - thread_safe (0.3.5) - tzinfo (1.2.2) + thread_safe (0.3.6) + tzinfo (1.2.3) thread_safe (~> 0.1) - unicode-display_width (1.1.2) + unicode-display_width (1.3.0) PLATFORMS ruby @@ -62,7 +63,7 @@ DEPENDENCIES pry rake rspec - rubocop (~> 0.45) + rubocop (~> 0.50.0) rubocop-migrations rubocop-rspec safe_yaml diff --git a/Makefile b/Makefile index 3071b349..c6dfc828 100644 --- a/Makefile +++ b/Makefile @@ -6,11 +6,11 @@ image: docker build --rm -t $(IMAGE_NAME) . test: image - docker run --rm $(IMAGE_NAME) sh -c "cd /usr/src/app && bundle exec rake" + docker run --rm $(IMAGE_NAME) sh -c "cd /usr/src/app && bundle install --with=test && bundle exec rake" docs: image docker run --rm \ --user root \ --workdir /usr/src/app \ --volume $(PWD):/usr/src/app \ - $(IMAGE_NAME) sh -c "bundle exec rake docs:scrape" + $(IMAGE_NAME) sh -c "apk --update add git && bundle exec rake docs:scrape" diff --git a/Rakefile b/Rakefile index 88e1fa2b..d7dc9f91 100644 --- a/Rakefile +++ b/Rakefile @@ -1,7 +1,11 @@ # frozen_string_literal: true -require "rspec/core/rake_task" - Rake.add_rakelib "lib/tasks" -RSpec::Core::RakeTask.new(:spec) -task default: :spec + +begin + require "rspec/core/rake_task" + + RSpec::Core::RakeTask.new(:spec) + task default: :spec +rescue LoadError +end diff --git a/config/contents/bundler/insecure_protocol_source.md b/config/contents/bundler/insecure_protocol_source.md new file mode 100644 index 00000000..b405c76f --- /dev/null +++ b/config/contents/bundler/insecure_protocol_source.md @@ -0,0 +1,22 @@ +The symbol argument `:gemcutter`, `:rubygems` and `:rubyforge` +are deprecated. So please change your source to URL string that +'https://rubygems.org' if possible, or 'http://rubygems.org' if not. + +This autocorrect will replace these symbols with 'https://rubygems.org'. +Because it is secure, HTTPS request is strongly recommended. And in +most use cases HTTPS will be fine. + +However, it don't replace all `sources` of `http://` with `https://`. +For example, when specifying an internal gem server using HTTP on the +intranet, a use case where HTTPS can not be specified was considered. +Consider using HTTP only if you can not use HTTPS. + +### Example: + # bad + source :gemcutter + source :rubygems + source :rubyforge + + # good + source 'https://rubygems.org' # strongly recommended + source 'http://rubygems.org' \ No newline at end of file diff --git a/config/contents/bundler/ordered_gems.md b/config/contents/bundler/ordered_gems.md index 9a36db79..84d8f9a2 100644 --- a/config/contents/bundler/ordered_gems.md +++ b/config/contents/bundler/ordered_gems.md @@ -1,4 +1,5 @@ -Gems in consecutive lines should be alphabetically sorted +Gems should be alphabetically sorted within groups. + ### Example: # bad gem 'rubocop' @@ -11,4 +12,10 @@ Gems in consecutive lines should be alphabetically sorted # good gem 'rubocop' + gem 'rspec' + + # good only if TreatCommentsAsGroupSeparators is true + # For code quality + gem 'rubocop' + # For tests gem 'rspec' \ No newline at end of file diff --git a/config/contents/lint/ambiguous_block_association.md b/config/contents/lint/ambiguous_block_association.md new file mode 100644 index 00000000..455ef0d2 --- /dev/null +++ b/config/contents/lint/ambiguous_block_association.md @@ -0,0 +1,21 @@ +This cop checks for ambiguous block association with method +when param passed without parentheses. + +### Example: + + # bad + some_method a { |val| puts val } + +### Example: + + # good + # With parentheses, there's no ambiguity. + some_method(a) { |val| puts val } + + # good + # Operator methods require no disambiguation + foo == bar { |b| b.baz } + + # good + # Lambda arguments require no disambiguation + foo = ->(bar) { bar.baz } \ No newline at end of file diff --git a/config/contents/lint/ambiguous_operator.md b/config/contents/lint/ambiguous_operator.md index 62dc2876..733a4a97 100644 --- a/config/contents/lint/ambiguous_operator.md +++ b/config/contents/lint/ambiguous_operator.md @@ -2,11 +2,16 @@ This cop checks for ambiguous operators in the first argument of a method invocation without parentheses. ### Example: - array = [1, 2, 3] + + # bad # The `*` is interpreted as a splat operator but it could possibly be - # a `*` method invocation (i.e. `do_something.*(array)`). - do_something *array + # a `*` method invocation (i.e. `do_something.*(some_array)`). + do_something *some_array + +### Example: + + # good # With parentheses, there's no ambiguity. - do_something(*array) \ No newline at end of file + do_something(*some_array) \ No newline at end of file diff --git a/config/contents/lint/ambiguous_regexp_literal.md b/config/contents/lint/ambiguous_regexp_literal.md index cbd59a4c..2c5b232f 100644 --- a/config/contents/lint/ambiguous_regexp_literal.md +++ b/config/contents/lint/ambiguous_regexp_literal.md @@ -2,10 +2,17 @@ This cop checks for ambiguous regexp literals in the first argument of a method invocation without parentheses. ### Example: + + # bad + # This is interpreted as a method invocation with a regexp literal, # but it could possibly be `/` method invocations. # (i.e. `do_something./(pattern)./(i)`) do_something /pattern/i +### Example: + + # good + # With parentheses, there's no ambiguity. do_something(/pattern/i) \ No newline at end of file diff --git a/config/contents/lint/assignment_in_condition.md b/config/contents/lint/assignment_in_condition.md new file mode 100644 index 00000000..60a37861 --- /dev/null +++ b/config/contents/lint/assignment_in_condition.md @@ -0,0 +1,18 @@ +This cop checks for assignments in the conditions of +if/while/until. + +### Example: + + # bad + + if some_var = true + do_something + end + +### Example: + + # good + + if some_var == true + do_something + end \ No newline at end of file diff --git a/config/contents/lint/block_alignment.md b/config/contents/lint/block_alignment.md index 21a6c722..b4b47d91 100644 --- a/config/contents/lint/block_alignment.md +++ b/config/contents/lint/block_alignment.md @@ -1,8 +1,8 @@ This cop checks whether the end keywords are aligned properly for do end blocks. -Three modes are supported through the `AlignWith` configuration -parameter: +Three modes are supported through the `EnforcedStyleAlignWith` +configuration parameter: `start_of_block` : the `end` shall be aligned with the start of the line where the `do` appeared. @@ -15,18 +15,40 @@ location. The autofixer will default to `start_of_line`. ### Example: - # either + # bad + + foo.bar + .each do + baz + end + +### Example: + + # EnforcedStyleAlignWith: either (default) + + # good + variable = lambda do |i| i end - # start_of_block +### Example: + + # EnforcedStyleAlignWith: start_of_block + + # good + foo.bar .each do baz end - # start_of_line +### Example: + + # EnforcedStyleAlignWith: start_of_line + + # good + foo.bar .each do baz diff --git a/config/contents/lint/boolean_symbol.md b/config/contents/lint/boolean_symbol.md new file mode 100644 index 00000000..bb4fe218 --- /dev/null +++ b/config/contents/lint/boolean_symbol.md @@ -0,0 +1,18 @@ +This cop checks for `:true` and `:false` symbols. +In most cases it would be a typo. + +### Example: + + # bad + :true + + # good + true + +### Example: + + # bad + :false + + # good + false \ No newline at end of file diff --git a/config/contents/lint/circular_argument_reference.md b/config/contents/lint/circular_argument_reference.md index 4bc805f7..628c4239 100644 --- a/config/contents/lint/circular_argument_reference.md +++ b/config/contents/lint/circular_argument_reference.md @@ -4,27 +4,41 @@ arguments and optional ordinal arguments. This cop mirrors a warning produced by MRI since 2.2. ### Example: + # bad + def bake(pie: pie) pie.heat_up end +### Example: + # good + def bake(pie:) pie.refrigerate end +### Example: + # good + def bake(pie: self.pie) pie.feed_to(user) end +### Example: + # bad + def cook(dry_ingredients = dry_ingredients) dry_ingredients.reduce(&:+) end +### Example: + # good + def cook(dry_ingredients = self.dry_ingredients) dry_ingredients.combine end \ No newline at end of file diff --git a/config/contents/lint/condition_position.md b/config/contents/lint/condition_position.md index 153c29ac..5f4557fd 100644 --- a/config/contents/lint/condition_position.md +++ b/config/contents/lint/condition_position.md @@ -3,7 +3,17 @@ if/while/until. ### Example: + # bad + if some_condition do_something + end + +### Example: + + # good + + if some_condition + do_something end \ No newline at end of file diff --git a/config/contents/lint/debugger.md b/config/contents/lint/debugger.md new file mode 100644 index 00000000..a66591c9 --- /dev/null +++ b/config/contents/lint/debugger.md @@ -0,0 +1,29 @@ +This cop checks for calls to debugger or pry. + +### Example: + + # bad (ok during development) + + # using pry + def some_method + binding.pry + do_something + end + +### Example: + + # bad (ok during development) + + # using byebug + def some_method + byebug + do_something + end + +### Example: + + # good + + def some_method + do_something + end \ No newline at end of file diff --git a/config/contents/lint/def_end_alignment.md b/config/contents/lint/def_end_alignment.md index aed3fea8..a67b073d 100644 --- a/config/contents/lint/def_end_alignment.md +++ b/config/contents/lint/def_end_alignment.md @@ -1,7 +1,7 @@ This cop checks whether the end keywords of method definitions are aligned properly. -Two modes are supported through the AlignWith configuration +Two modes are supported through the EnforcedStyleAlignWith configuration parameter. If it's set to `start_of_line` (which is the default), the `end` shall be aligned with the start of the line where the `def` keyword is. If it's set to `def`, the `end` shall be aligned with the @@ -9,5 +9,25 @@ keyword is. If it's set to `def`, the `end` shall be aligned with the ### Example: + # bad + + private def foo + end + +### Example: + + # EnforcedStyleAlignWith: start_of_line (default) + + # good + + private def foo + end + +### Example: + + # EnforcedStyleAlignWith: def + + # good + private def foo - end \ No newline at end of file + end \ No newline at end of file diff --git a/config/contents/lint/deprecated_class_methods.md b/config/contents/lint/deprecated_class_methods.md new file mode 100644 index 00000000..0ede887f --- /dev/null +++ b/config/contents/lint/deprecated_class_methods.md @@ -0,0 +1,13 @@ +This cop checks for uses of the deprecated class method usages. + +### Example: + + # bad + + File.exists?(some_path) + +### Example: + + # good + + File.exist?(some_path) \ No newline at end of file diff --git a/config/contents/lint/duplicate_case_condition.md b/config/contents/lint/duplicate_case_condition.md index 3dccf3b8..691ee2fe 100644 --- a/config/contents/lint/duplicate_case_condition.md +++ b/config/contents/lint/duplicate_case_condition.md @@ -3,10 +3,22 @@ used in case 'when' expressions. ### Example: - # bad - case x - when 'first' - do_something - when 'first' - do_something_else - end + # bad + + case x + when 'first' + do_something + when 'first' + do_something_else + end + +### Example: + + # good + + case x + when 'first' + do_something + when 'second' + do_something_else + end \ No newline at end of file diff --git a/config/contents/lint/duplicate_methods.md b/config/contents/lint/duplicate_methods.md index f210aafc..a38d165e 100644 --- a/config/contents/lint/duplicate_methods.md +++ b/config/contents/lint/duplicate_methods.md @@ -2,11 +2,35 @@ This cop checks for duplicated instance (or singleton) method definitions. ### Example: + # bad + def duplicated 1 end def duplicated 2 + end + +### Example: + + # bad + + def duplicated + 1 + end + + alias duplicated other_duplicated + +### Example: + + # good + + def duplicated + 1 + end + + def other_duplicated + 2 end \ No newline at end of file diff --git a/config/contents/lint/duplicated_key.md b/config/contents/lint/duplicated_key.md index 6ec346f2..6bab0890 100644 --- a/config/contents/lint/duplicated_key.md +++ b/config/contents/lint/duplicated_key.md @@ -3,4 +3,13 @@ This cop checks for duplicated keys in hash literals. This cop mirrors a warning in Ruby 2.2. ### Example: - hash = { food: 'apple', food: 'orange' } \ No newline at end of file + + # bad + + hash = { food: 'apple', food: 'orange' } + +### Example: + + # good + + hash = { food: 'apple', other_food: 'orange' } \ No newline at end of file diff --git a/config/contents/lint/each_with_object_argument.md b/config/contents/lint/each_with_object_argument.md index b2a37be4..2cbab47c 100644 --- a/config/contents/lint/each_with_object_argument.md +++ b/config/contents/lint/each_with_object_argument.md @@ -6,4 +6,13 @@ It's definitely a bug. ### Example: - sum = numbers.each_with_object(0) { |e, a| a += e } \ No newline at end of file + # bad + + sum = numbers.each_with_object(0) { |e, a| a += e } + +### Example: + + # good + + num = 0 + sum = numbers.each_with_object(num) { |e, a| a += e } \ No newline at end of file diff --git a/config/contents/lint/else_layout.md b/config/contents/lint/else_layout.md index 23715628..4f64659e 100644 --- a/config/contents/lint/else_layout.md +++ b/config/contents/lint/else_layout.md @@ -4,8 +4,21 @@ which is usually a mistake. ### Example: + # bad + if something ... else do_this do_that + end + +### Example: + + # good + + if something + ... + else + do_this + do_that end \ No newline at end of file diff --git a/config/contents/lint/empty_ensure.md b/config/contents/lint/empty_ensure.md new file mode 100644 index 00000000..af1a57a7 --- /dev/null +++ b/config/contents/lint/empty_ensure.md @@ -0,0 +1,39 @@ +This cop checks for empty `ensure` blocks + +### Example: + + # bad + + def some_method + do_something + ensure + end + +### Example: + + # bad + + begin + do_something + ensure + end + +### Example: + + # good + + def some_method + do_something + ensure + do_something_else + end + +### Example: + + # good + + begin + do_something + ensure + do_something_else + end \ No newline at end of file diff --git a/config/contents/lint/empty_expression.md b/config/contents/lint/empty_expression.md index 00c073f4..16f8d0ad 100644 --- a/config/contents/lint/empty_expression.md +++ b/config/contents/lint/empty_expression.md @@ -3,7 +3,17 @@ This cop checks for the presence of empty expressions. ### Example: # bad + foo = () if () bar + end + +### Example: + + # good + + foo = (some_expression) + if (some_expression) + bar end \ No newline at end of file diff --git a/config/contents/lint/empty_interpolation.md b/config/contents/lint/empty_interpolation.md index f07b17f1..e6b9e1cd 100644 --- a/config/contents/lint/empty_interpolation.md +++ b/config/contents/lint/empty_interpolation.md @@ -2,4 +2,12 @@ This cop checks for empty interpolation. ### Example: - "result is #{}" \ No newline at end of file + # bad + + "result is #{}" + +### Example: + + # good + + "result is #{some_result}" \ No newline at end of file diff --git a/config/contents/lint/empty_when.md b/config/contents/lint/empty_when.md index da74fb3a..1d345d6e 100644 --- a/config/contents/lint/empty_when.md +++ b/config/contents/lint/empty_when.md @@ -3,7 +3,17 @@ This cop checks for the presence of `when` branches without a body. ### Example: # bad + case foo when bar then 1 when baz then # nothing + end + +### Example: + + # good + + case foo + when bar then 1 + when baz then 2 end \ No newline at end of file diff --git a/config/contents/lint/end_alignment.md b/config/contents/lint/end_alignment.md index cc8ca6b1..4185a455 100644 --- a/config/contents/lint/end_alignment.md +++ b/config/contents/lint/end_alignment.md @@ -1,7 +1,7 @@ This cop checks whether the end keywords are aligned properly. -Three modes are supported through the `AlignWith` configuration -parameter: +Three modes are supported through the `EnforcedStyleAlignWith` +configuration parameter: If it's set to `keyword` (which is the default), the `end` shall be aligned with the start of the keyword (if, class, etc.). @@ -13,15 +13,35 @@ If it's set to `start_of_line`, the `end` shall be aligned with the start of the line where the matching keyword appears. ### Example: + + # bad + + variable = if true + end + +### Example: + + # EnforcedStyleAlignWith: keyword (default) + # good - # keyword style + variable = if true end - # variable style +### Example: + + # EnforcedStyleAlignWith: variable + + # good + variable = if true end - # start_of_line style +### Example: + + # EnforcedStyleAlignWith: start_of_line + + # good + puts(if true end) \ No newline at end of file diff --git a/config/contents/lint/end_in_method.md b/config/contents/lint/end_in_method.md new file mode 100644 index 00000000..34f440e0 --- /dev/null +++ b/config/contents/lint/end_in_method.md @@ -0,0 +1,24 @@ +This cop checks for END blocks in method definitions. + +### Example: + + # bad + + def some_method + END { do_something } + end + +### Example: + + # good + + def some_method + at_exit { do_something } + end + +### Example: + + # good + + # outside defs + END { do_something } \ No newline at end of file diff --git a/config/contents/lint/ensure_return.md b/config/contents/lint/ensure_return.md new file mode 100644 index 00000000..c155ed2e --- /dev/null +++ b/config/contents/lint/ensure_return.md @@ -0,0 +1,22 @@ +This cop checks for *return* from an *ensure* block. + +### Example: + + # bad + + begin + do_something + ensure + do_something_else + return + end + +### Example: + + # good + + begin + do_something + ensure + do_something_else + end \ No newline at end of file diff --git a/config/contents/lint/float_out_of_range.md b/config/contents/lint/float_out_of_range.md index 5da6a5ca..c910b236 100644 --- a/config/contents/lint/float_out_of_range.md +++ b/config/contents/lint/float_out_of_range.md @@ -3,8 +3,13 @@ really really really really really big. Too big. No-one needs Floats that big. If you need a float that big, something is wrong with you. ### Example: + # bad + float = 3.0e400 +### Example: + # good + float = 42.9 \ No newline at end of file diff --git a/config/contents/lint/format_parameter_mismatch.md b/config/contents/lint/format_parameter_mismatch.md index b66988b3..8945029e 100644 --- a/config/contents/lint/format_parameter_mismatch.md +++ b/config/contents/lint/format_parameter_mismatch.md @@ -4,4 +4,12 @@ passed as arguments. ### Example: + # bad + format('A value: %s and another: %i', a_value) + +### Example: + + # good + + format('A value: %s and another: %i', a_value, another) \ No newline at end of file diff --git a/config/contents/lint/handle_exceptions.md b/config/contents/lint/handle_exceptions.md new file mode 100644 index 00000000..18f4c96a --- /dev/null +++ b/config/contents/lint/handle_exceptions.md @@ -0,0 +1,41 @@ +This cop checks for *rescue* blocks with no body. + +### Example: + + # bad + + def some_method + do_something + rescue + # do nothing + end + +### Example: + + # bad + + begin + do_something + rescue + # do nothing + end + +### Example: + + # good + + def some_method + do_something + rescue + handle_exception + end + +### Example: + + # good + + begin + do_something + rescue + handle_exception + end \ No newline at end of file diff --git a/config/contents/lint/implicit_string_concatenation.md b/config/contents/lint/implicit_string_concatenation.md index e957b838..e0ec682e 100644 --- a/config/contents/lint/implicit_string_concatenation.md +++ b/config/contents/lint/implicit_string_concatenation.md @@ -2,10 +2,15 @@ This cop checks for implicit string concatenation of string literals which are on the same line. ### Example: + # bad + array = ['Item 1' 'Item 2'] +### Example: + # good + array = ['Item 1Item 2'] array = ['Item 1' + 'Item 2'] array = [ diff --git a/config/contents/lint/ineffective_access_modifier.md b/config/contents/lint/ineffective_access_modifier.md index 8238b25d..7ea298fd 100644 --- a/config/contents/lint/ineffective_access_modifier.md +++ b/config/contents/lint/ineffective_access_modifier.md @@ -4,7 +4,9 @@ singleton methods private/protected. `private_class_method` can be used for that. ### Example: + # bad + class C private @@ -13,7 +15,10 @@ used for that. end end +### Example: + # good + class C def self.method puts 'hi' @@ -22,6 +27,10 @@ used for that. private_class_method :method end +### Example: + + # good + class C class << self private diff --git a/config/contents/lint/interpolation_check.md b/config/contents/lint/interpolation_check.md new file mode 100644 index 00000000..c74e058f --- /dev/null +++ b/config/contents/lint/interpolation_check.md @@ -0,0 +1,13 @@ +This cop checks for interpolation in a single quoted string. + +### Example: + + # bad + + foo = 'something with #{interpolation} inside' + +### Example: + + # good + + foo = "something with #{interpolation} inside" \ No newline at end of file diff --git a/config/contents/lint/invalid_character_literal.md b/config/contents/lint/invalid_character_literal.md index a4b42eba..20d01a72 100644 --- a/config/contents/lint/invalid_character_literal.md +++ b/config/contents/lint/invalid_character_literal.md @@ -11,4 +11,7 @@ warning without syntax errors. ^ ### Example: + + # bad + p(? ) \ No newline at end of file diff --git a/config/contents/lint/literal_in_condition.md b/config/contents/lint/literal_in_condition.md index 622844dd..8a7d79be 100644 --- a/config/contents/lint/literal_in_condition.md +++ b/config/contents/lint/literal_in_condition.md @@ -4,10 +4,24 @@ if/while/until. ### Example: + # bad + if 20 do_something end +### Example: + + # bad + if some_var && true do_something end + +### Example: + + # good + + if some_var && some_condition + do_something + end \ No newline at end of file diff --git a/config/contents/lint/literal_in_interpolation.md b/config/contents/lint/literal_in_interpolation.md index 2d64b0a2..859ee1d0 100644 --- a/config/contents/lint/literal_in_interpolation.md +++ b/config/contents/lint/literal_in_interpolation.md @@ -2,4 +2,12 @@ This cop checks for interpolated literals. ### Example: - "result is #{10}" \ No newline at end of file + # bad + + "result is #{10}" + +### Example: + + # good + + "result is 10" \ No newline at end of file diff --git a/config/contents/lint/loop.md b/config/contents/lint/loop.md new file mode 100644 index 00000000..63d115a0 --- /dev/null +++ b/config/contents/lint/loop.md @@ -0,0 +1,37 @@ +This cop checks for uses of *begin...end while/until something*. + +### Example: + + # bad + + # using while + begin + do_something + end while some_condition + +### Example: + + # bad + + # using until + begin + do_something + end until some_condition + +### Example: + + # good + + # using while + while some_condition + do_something + end + +### Example: + + # good + + # using until + until some_condition + do_something + end \ No newline at end of file diff --git a/config/contents/lint/multiple_compare.md b/config/contents/lint/multiple_compare.md new file mode 100644 index 00000000..ad4bdabe --- /dev/null +++ b/config/contents/lint/multiple_compare.md @@ -0,0 +1,18 @@ +In math and Python, we can use `x < y < z` style comparison to compare +multiple value. However, we can't use the comparison in Ruby. However, +the comparison is not syntax error. This cop checks the bad usage of +comparison operators. + +### Example: + + # bad + + x < y < z + 10 <= x <= 20 + +### Example: + + # good + + x < y && y < z + 10 <= x && x <= 20 \ No newline at end of file diff --git a/config/contents/lint/nested_method_definition.md b/config/contents/lint/nested_method_definition.md index df93cb89..32e0b308 100644 --- a/config/contents/lint/nested_method_definition.md +++ b/config/contents/lint/nested_method_definition.md @@ -1,6 +1,9 @@ This cop checks for nested method definitions. ### Example: + + # bad + # `bar` definition actually produces methods in the same scope # as the outer `foo` method. Furthermore, the `bar` method # will be redefined every time `foo` is invoked. @@ -8,3 +11,41 @@ This cop checks for nested method definitions. def bar end end + +### Example: + + # good + + def foo + bar = -> { puts 'hello' } + bar.call + end + +### Example: + + # good + + def foo + self.class_eval do + def bar + end + end + end + + def foo + self.module_exec do + def bar + end + end + end + +### Example: + + # good + + def foo + class << self + def bar + end + end + end \ No newline at end of file diff --git a/config/contents/lint/next_without_accumulator.md b/config/contents/lint/next_without_accumulator.md index afa476c3..b3226b11 100644 --- a/config/contents/lint/next_without_accumulator.md +++ b/config/contents/lint/next_without_accumulator.md @@ -1,13 +1,18 @@ Don't omit the accumulator when calling `next` in a `reduce` block. ### Example: + # bad + result = (1..4).reduce(0) do |acc, i| next if i.odd? acc + i end +### Example: + # good + result = (1..4).reduce(0) do |acc, i| next acc if i.odd? acc + i diff --git a/config/contents/lint/non_local_exit_from_iterator.md b/config/contents/lint/non_local_exit_from_iterator.md index 1b8036c9..25268aa1 100644 --- a/config/contents/lint/non_local_exit_from_iterator.md +++ b/config/contents/lint/non_local_exit_from_iterator.md @@ -1,8 +1,13 @@ -This cop checks for non-local exit from iterator, without return value. -It warns only when satisfies all of these: `return` doesn't have return -value, the block is preceded by a method chain, the block has arguments, -and the method which receives the block is not `define_method` -or `define_singleton_method`. +This cop checks for non-local exits from iterators without a return +value. It registers an offense under these conditions: + + - No value is returned, + - the block is preceded by a method chain, + - the block has arguments, + - the method which receives the block is not `define_method` + or `define_singleton_method`, + - the return is not contained in an inner scope, e.g. a lambda or a + method definition. ### Example: diff --git a/config/contents/lint/parentheses_as_grouped_expression.md b/config/contents/lint/parentheses_as_grouped_expression.md index 336f2db7..8b765e01 100644 --- a/config/contents/lint/parentheses_as_grouped_expression.md +++ b/config/contents/lint/parentheses_as_grouped_expression.md @@ -3,4 +3,12 @@ parenthesis. ### Example: - puts (x + y) \ No newline at end of file + # bad + + puts (x + y) + +### Example: + + # good + + puts(x + y) \ No newline at end of file diff --git a/config/contents/lint/percent_string_array.md b/config/contents/lint/percent_string_array.md index fe7e821c..4f674b5a 100644 --- a/config/contents/lint/percent_string_array.md +++ b/config/contents/lint/percent_string_array.md @@ -1,7 +1,17 @@ -This cop checks for quotes and commas in %w, e.g. +This cop checks for quotes and commas in %w, e.g. `%w('foo', "bar")` - `%w('foo', "bar")` - -it is more likely that the additional characters are unintended (for +It is more likely that the additional characters are unintended (for example, mistranslating an array of literals to percent string notation) -rather than meant to be part of the resulting strings. \ No newline at end of file +rather than meant to be part of the resulting strings. + +### Example: + + # bad + + %w('foo', "bar") + +### Example: + + # good + + %w(foo bar) \ No newline at end of file diff --git a/config/contents/lint/percent_symbol_array.md b/config/contents/lint/percent_symbol_array.md index c247d5f9..bb4331de 100644 --- a/config/contents/lint/percent_symbol_array.md +++ b/config/contents/lint/percent_symbol_array.md @@ -1,7 +1,17 @@ -This cop checks for colons and commas in %i, e.g. +This cop checks for colons and commas in %i, e.g. `%i(:foo, :bar)` - `%i(:foo, :bar)` - -it is more likely that the additional characters are unintended (for +It is more likely that the additional characters are unintended (for example, mistranslating an array of literals to percent string notation) -rather than meant to be part of the resulting symbols. \ No newline at end of file +rather than meant to be part of the resulting symbols. + +### Example: + + # bad + + %i(:foo, :bar) + +### Example: + + # good + + %i(foo bar) \ No newline at end of file diff --git a/config/contents/lint/rand_one.md b/config/contents/lint/rand_one.md index 4b9fcd04..ecd016d8 100644 --- a/config/contents/lint/rand_one.md +++ b/config/contents/lint/rand_one.md @@ -4,10 +4,14 @@ Such calls always return `0`. ### Example: # bad + rand 1 Kernel.rand(-1) rand 1.0 rand(-1.0) +### Example: + # good - 0 \ No newline at end of file + + 0 # just use 0 instead \ No newline at end of file diff --git a/config/contents/lint/redundant_with_index.md b/config/contents/lint/redundant_with_index.md new file mode 100644 index 00000000..3dc86d07 --- /dev/null +++ b/config/contents/lint/redundant_with_index.md @@ -0,0 +1,22 @@ +This cop checks for redundant `with_index`. + +### Example: + # bad + ary.each_with_index do |v| + v + end + + # good + ary.each do |v| + v + end + + # bad + ary.each.with_index do |v| + v + end + + # good + ary.each do |v| + v + end diff --git a/config/contents/lint/require_parentheses.md b/config/contents/lint/require_parentheses.md index 18ba6dc6..da99dcde 100644 --- a/config/contents/lint/require_parentheses.md +++ b/config/contents/lint/require_parentheses.md @@ -9,6 +9,14 @@ an operand of &&/||. ### Example: + # bad + if day.is? :tuesday && month == :jan ... - end \ No newline at end of file + end + +### Example: + + # good + + if day.is?(:tuesday) && month == :jan \ No newline at end of file diff --git a/config/contents/lint/rescue_exception.md b/config/contents/lint/rescue_exception.md new file mode 100644 index 00000000..ebd8411f --- /dev/null +++ b/config/contents/lint/rescue_exception.md @@ -0,0 +1,21 @@ +This cop checks for *rescue* blocks targeting the Exception class. + +### Example: + + # bad + + begin + do_something + rescue Exception + handle_exception + end + +### Example: + + # good + + begin + do_something + rescue ArgumentError + handle_exception + end \ No newline at end of file diff --git a/config/contents/lint/rescue_type.md b/config/contents/lint/rescue_type.md new file mode 100644 index 00000000..cfd8ef2e --- /dev/null +++ b/config/contents/lint/rescue_type.md @@ -0,0 +1,31 @@ +Check for arguments to `rescue` that will result in a `TypeError` +if an exception is raised. + +### Example: + # bad + begin + bar + rescue nil + baz + end + + # bad + def foo + bar + rescue 1, 'a', "#{b}", 0.0, [], {} + baz + end + + # good + begin + bar + rescue + baz + end + + # good + def foo + bar + rescue NameError + baz + end \ No newline at end of file diff --git a/config/contents/lint/rescue_without_error_class.md b/config/contents/lint/rescue_without_error_class.md new file mode 100644 index 00000000..8d75472a --- /dev/null +++ b/config/contents/lint/rescue_without_error_class.md @@ -0,0 +1,17 @@ +This cop checks for uses of `rescue` with no error class specified. + +### Example: + + # good + begin + foo + rescue BarError + bar + end + + # bad + begin + foo + rescue + bar + end \ No newline at end of file diff --git a/config/contents/lint/return_in_void_context.md b/config/contents/lint/return_in_void_context.md new file mode 100644 index 00000000..3c378996 --- /dev/null +++ b/config/contents/lint/return_in_void_context.md @@ -0,0 +1,28 @@ +This cop checks for the use of a return with a value in a context +where the value will be ignored. (initialize and setter methods) + +### Example: + + # bad + def initialize + foo + return :qux if bar? + baz + end + + def foo=(bar) + return 42 + end + +### Example: + + # good + def initialize + foo + return if bar? + baz + end + + def foo=(bar) + return + end \ No newline at end of file diff --git a/config/contents/lint/safe_navigation_chain.md b/config/contents/lint/safe_navigation_chain.md new file mode 100644 index 00000000..d4ba8403 --- /dev/null +++ b/config/contents/lint/safe_navigation_chain.md @@ -0,0 +1,20 @@ +The safe navigation operator returns nil if the receiver is +nil. If you chain an ordinary method call after a safe +navigation operator, it raises NoMethodError. We should use a +safe navigation operator after a safe navigation operator. +This cop checks for the problem outlined above. + +### Example: + + # bad + + x&.foo.bar + x&.foo + bar + x&.foo[bar] + +### Example: + + # good + + x&.foo&.bar + x&.foo || bar \ No newline at end of file diff --git a/config/contents/lint/shadowed_exception.md b/config/contents/lint/shadowed_exception.md index 02f43cc9..f8f7a240 100644 --- a/config/contents/lint/shadowed_exception.md +++ b/config/contents/lint/shadowed_exception.md @@ -3,7 +3,9 @@ less specific exception being rescued before a more specific exception is rescued. ### Example: + # bad + begin something rescue Exception @@ -12,7 +14,10 @@ exception is rescued. handle_standard_error end +### Example: + # good + begin something rescue StandardError diff --git a/config/contents/lint/shadowing_outer_local_variable.md b/config/contents/lint/shadowing_outer_local_variable.md index 634cb302..e203a051 100644 --- a/config/contents/lint/shadowing_outer_local_variable.md +++ b/config/contents/lint/shadowing_outer_local_variable.md @@ -1,4 +1,28 @@ This cop looks for use of the same name as outer local variables for block arguments or block local variables. This is a mimic of the warning -"shadowing outer local variable - foo" from `ruby -cw`. \ No newline at end of file +"shadowing outer local variable - foo" from `ruby -cw`. + +### Example: + + # bad + + def some_method + foo = 1 + + 2.times do |foo| # shadowing outer `foo` + do_something(foo) + end + end + +### Example: + + # good + + def some_method + foo = 1 + + 2.times do |bar| + do_something(bar) + end + end \ No newline at end of file diff --git a/config/contents/lint/string_conversion_in_interpolation.md b/config/contents/lint/string_conversion_in_interpolation.md index d57c1973..49db53fa 100644 --- a/config/contents/lint/string_conversion_in_interpolation.md +++ b/config/contents/lint/string_conversion_in_interpolation.md @@ -3,4 +3,12 @@ which is redundant. ### Example: - "result is #{something.to_s}" \ No newline at end of file + # bad + + "result is #{something.to_s}" + +### Example: + + # good + + "result is #{something}" \ No newline at end of file diff --git a/config/contents/lint/underscore_prefixed_variable_name.md b/config/contents/lint/underscore_prefixed_variable_name.md new file mode 100644 index 00000000..a5a77a76 --- /dev/null +++ b/config/contents/lint/underscore_prefixed_variable_name.md @@ -0,0 +1,26 @@ +This cop checks for underscore-prefixed variables that are actually +used. + +### Example: + + # bad + + [1, 2, 3].each do |_num| + do_something(_num) + end + +### Example: + + # good + + [1, 2, 3].each do |num| + do_something(num) + end + +### Example: + + # good + + [1, 2, 3].each do |_num| + do_something # not using `_num` + end \ No newline at end of file diff --git a/config/contents/lint/unified_integer.md b/config/contents/lint/unified_integer.md index 33e3b235..b8b2ac73 100644 --- a/config/contents/lint/unified_integer.md +++ b/config/contents/lint/unified_integer.md @@ -1,9 +1,14 @@ This cop checks for using Fixnum or Bignum constant. ### Example: + # bad + 1.is_a?(Fixnum) 1.is_a?(Bignum) +### Example: + # good + 1.is_a?(Integer) \ No newline at end of file diff --git a/config/contents/lint/unneeded_splat_expansion.md b/config/contents/lint/unneeded_splat_expansion.md index 14dff6cb..af4953f0 100644 --- a/config/contents/lint/unneeded_splat_expansion.md +++ b/config/contents/lint/unneeded_splat_expansion.md @@ -1,7 +1,9 @@ This cop checks for unneeded usages of splat expansion ### Example: + # bad + a = *[1, 2, 3] a = *'a' a = *1 @@ -19,7 +21,10 @@ This cop checks for unneeded usages of splat expansion baz end +### Example: + # good + c = [1, 2, 3] a = *c a, b = *c diff --git a/config/contents/lint/unreachable_code.md b/config/contents/lint/unreachable_code.md index fcfcbce9..e00b649f 100644 --- a/config/contents/lint/unreachable_code.md +++ b/config/contents/lint/unreachable_code.md @@ -1,3 +1,31 @@ This cop checks for unreachable code. The check are based on the presence of flow of control -statement in non-final position in *begin*(implicit) blocks. \ No newline at end of file +statement in non-final position in *begin*(implicit) blocks. + +### Example: + + # bad + + def some_method + return + do_something + end + + # bad + + def some_method + if cond + return + else + return + end + do_something + end + +### Example: + + # good + + def some_method + do_something + end \ No newline at end of file diff --git a/config/contents/lint/unused_block_argument.md b/config/contents/lint/unused_block_argument.md index d5715db9..d4263b69 100644 --- a/config/contents/lint/unused_block_argument.md +++ b/config/contents/lint/unused_block_argument.md @@ -2,30 +2,32 @@ This cop checks for unused block arguments. ### Example: - #good + # bad do_something do |used, unused| puts used end - do_something do + do_something do |bar| puts :foo end - define_method(:foo) do |_bar| + define_method(:foo) do |bar| puts :baz end - # bad +### Example: + + #good do_something do |used, _unused| puts used end - do_something do |bar| + do_something do puts :foo end - define_method(:foo) do |bar| + define_method(:foo) do |_bar| puts :baz end \ No newline at end of file diff --git a/config/contents/lint/unused_method_argument.md b/config/contents/lint/unused_method_argument.md index f7ffa118..05105013 100644 --- a/config/contents/lint/unused_method_argument.md +++ b/config/contents/lint/unused_method_argument.md @@ -2,6 +2,16 @@ This cop checks for unused method arguments. ### Example: + # bad + def some_method(used, unused, _unused_but_allowed) puts used + end + +### Example: + + # good + + def some_method(used, _unused, _unused_but_allowed) + puts used end \ No newline at end of file diff --git a/config/contents/lint/uri_escape_unescape.md b/config/contents/lint/uri_escape_unescape.md new file mode 100644 index 00000000..5ac52c40 --- /dev/null +++ b/config/contents/lint/uri_escape_unescape.md @@ -0,0 +1,25 @@ +This cop identifies places where `URI.escape` can be replaced by +`CGI.escape`, `URI.encode_www_form` or `URI.encode_www_form_component` +depending on your specific use case. +Also this cop identifies places where `URI.unescape` can be replaced by +`CGI.unescape`, `URI.decode_www_form` or `URI.decode_www_form_component` +depending on your specific use case. + +### Example: + # bad + URI.escape('http://example.com') + URI.encode('http://example.com') + + # good + CGI.escape('http://example.com') + URI.encode_www_form('http://example.com') + URI.encode_www_form_component('http://example.com') + + # bad + URI.unescape(enc_uri) + URI.decode(enc_uri) + + # good + CGI.unescape(enc_uri) + URI.decode_www_form(enc_uri) + URI.decode_www_form_component(enc_uri) \ No newline at end of file diff --git a/config/contents/lint/uri_regexp.md b/config/contents/lint/uri_regexp.md new file mode 100644 index 00000000..269f95eb --- /dev/null +++ b/config/contents/lint/uri_regexp.md @@ -0,0 +1,9 @@ +This cop identifies places where `URI.regexp` is obsolete and should +not be used. Instead, use `URI::DEFAULT_PARSER.make_regexp`. + +### Example: + # bad + URI.regexp('http://example.com') + + # good + URI::DEFAULT_PARSER.make_regexp('http://example.com') diff --git a/config/contents/lint/useless_access_modifier.md b/config/contents/lint/useless_access_modifier.md index 7e422305..244449bd 100644 --- a/config/contents/lint/useless_access_modifier.md +++ b/config/contents/lint/useless_access_modifier.md @@ -72,4 +72,16 @@ are not redundant. def some_other_private_method end + end + +### Example: + # Lint/UselessAccessModifier: + # MethodCreatingMethods: + # - delegate + require 'active_support/core_ext/module/delegation' + class Foo + # this is not redundant because `delegate` creates methods + private + + delegate :method_a, to: :method_b end \ No newline at end of file diff --git a/config/contents/lint/useless_assignment.md b/config/contents/lint/useless_assignment.md index 42a33b4c..2ed8d7e2 100644 --- a/config/contents/lint/useless_assignment.md +++ b/config/contents/lint/useless_assignment.md @@ -6,4 +6,22 @@ The basic idea for this cop was from the warning of `ruby -cw`: Currently this cop has advanced logic that detects unreferenced reassignments and properly handles varied cases such as branch, loop, -rescue, ensure, etc. \ No newline at end of file +rescue, ensure, etc. + +### Example: + + # bad + + def some_method + some_var = 1 + do_something + end + +### Example: + + # good + + def some_method + some_var = 1 + do_something(some_var) + end \ No newline at end of file diff --git a/config/contents/lint/useless_comparison.md b/config/contents/lint/useless_comparison.md index fa38ec62..9aacab37 100644 --- a/config/contents/lint/useless_comparison.md +++ b/config/contents/lint/useless_comparison.md @@ -2,4 +2,6 @@ This cop checks for comparison of something with itself. ### Example: - x.top >= x.top \ No newline at end of file + # bad + + x.top >= x.top \ No newline at end of file diff --git a/config/contents/lint/useless_else_without_rescue.md b/config/contents/lint/useless_else_without_rescue.md index 0eec0fef..0aae7485 100644 --- a/config/contents/lint/useless_else_without_rescue.md +++ b/config/contents/lint/useless_else_without_rescue.md @@ -1,8 +1,23 @@ This cop checks for useless `else` in `begin..end` without `rescue`. ### Example: + + # bad + + begin + do_something + else + do_something_else # This will never be run. + end + +### Example: + + # good + begin do_something + rescue + handle_errors else - handle_errors # This will never be run. + do_something_else end \ No newline at end of file diff --git a/config/contents/lint/useless_setter_call.md b/config/contents/lint/useless_setter_call.md index 239dfd5d..fa5ca9e6 100644 --- a/config/contents/lint/useless_setter_call.md +++ b/config/contents/lint/useless_setter_call.md @@ -3,7 +3,19 @@ expression of a function definition. ### Example: - def something - x = Something.new - x.attr = 5 - end \ No newline at end of file + # bad + + def something + x = Something.new + x.attr = 5 + end + +### Example: + + # good + + def something + x = Something.new + x.attr = 5 + x + end \ No newline at end of file diff --git a/config/contents/lint/void.md b/config/contents/lint/void.md new file mode 100644 index 00000000..816a07d7 --- /dev/null +++ b/config/contents/lint/void.md @@ -0,0 +1,38 @@ +This cop checks for operators, variables and literals used +in void context. + +### Example: + + # bad + + def some_method + some_num * 10 + do_something + end + +### Example: + + # bad + + def some_method(some_var) + some_var + do_something + end + +### Example: + + # good + + def some_method + do_something + some_num * 10 + end + +### Example: + + # good + + def some_method(some_var) + do_something + some_var + end \ No newline at end of file diff --git a/config/contents/metrics/block_length.md b/config/contents/metrics/block_length.md index 68dfd3fa..585f1e86 100644 --- a/config/contents/metrics/block_length.md +++ b/config/contents/metrics/block_length.md @@ -1,3 +1,4 @@ This cop checks if the length of a block exceeds some maximum value. Comment lines can optionally be ignored. -The maximum allowed length is configurable. \ No newline at end of file +The maximum allowed length is configurable. +The cop can be configured to ignore blocks passed to certain methods. \ No newline at end of file diff --git a/config/contents/metrics/block_nesting.md b/config/contents/metrics/block_nesting.md index 67994d76..d575e978 100644 --- a/config/contents/metrics/block_nesting.md +++ b/config/contents/metrics/block_nesting.md @@ -1,5 +1,8 @@ This cop checks for excessive nesting of conditional and looping -constructs. Despite the cop's name, blocks are not considered as an -extra level of nesting. +constructs. + +You can configure if blocks are considered using the `CountBlocks` +option. When set to `false` (the default) blocks are not counted +towards the nesting level. Set to `true` to count blocks as well. The maximum level of nesting allowed is configurable. \ No newline at end of file diff --git a/config/contents/performance/caller.md b/config/contents/performance/caller.md new file mode 100644 index 00000000..618ecb1f --- /dev/null +++ b/config/contents/performance/caller.md @@ -0,0 +1,15 @@ +This cop identifies places where `caller[n]` +can be replaced by `caller(n..n).first`. + +### Example: + # bad + caller[1] + caller.first + caller_locations[1] + caller_locations.first + + # good + caller(2..2).first + caller(1..1).first + caller_locations(2..2).first + caller_locations(1..1).first \ No newline at end of file diff --git a/config/contents/performance/compare_with_block.md b/config/contents/performance/compare_with_block.md index 896044df..9cf8359f 100644 --- a/config/contents/performance/compare_with_block.md +++ b/config/contents/performance/compare_with_block.md @@ -7,6 +7,7 @@ This cop also checks `max` and `min` methods. array.sort { |a, b| a.foo <=> b.foo } array.max { |a, b| a.foo <=> b.foo } array.min { |a, b| a.foo <=> b.foo } + array.sort { |a, b| a[:foo] <=> b[:foo] } # good array.sort_by(&:foo) @@ -15,4 +16,5 @@ This cop also checks `max` and `min` methods. var.foo end array.max_by(&:foo) - array.min_by(&:foo) \ No newline at end of file + array.min_by(&:foo) + array.sort_by { |a| a[:foo] } \ No newline at end of file diff --git a/config/contents/performance/end_with.md b/config/contents/performance/end_with.md index d17db641..28288b6d 100644 --- a/config/contents/performance/end_with.md +++ b/config/contents/performance/end_with.md @@ -7,5 +7,4 @@ would suffice. 'abc'.match(/bc\Z/) # good - 'abc' =~ /ab/ - 'abc' =~ /\w*\Z/ \ No newline at end of file + 'abc'.end_with?('bc') \ No newline at end of file diff --git a/config/contents/performance/redundant_match.md b/config/contents/performance/redundant_match.md index d6645bdd..748bd177 100644 --- a/config/contents/performance/redundant_match.md +++ b/config/contents/performance/redundant_match.md @@ -1,4 +1,4 @@ -This cop identifies use of `Regexp#match` or `String#match in a context +This cop identifies use of `Regexp#match` or `String#match` in a context where the integral return value of `=~` would do just as well. ### Example: diff --git a/config/contents/performance/regexp_match.md b/config/contents/performance/regexp_match.md new file mode 100644 index 00000000..a7e00f14 --- /dev/null +++ b/config/contents/performance/regexp_match.md @@ -0,0 +1,55 @@ +In Ruby 2.4, `String#match?`, `Regexp#match?` and `Symbol#match?` +have been added. The methods are faster than `match`. +Because the methods avoid creating a `MatchData` object or saving +backref. +So, when `MatchData` is not used, use `match?` instead of `match`. + +### Example: + # bad + def foo + if x =~ /re/ + do_something + end + end + + # bad + def foo + if x.match(/re/) + do_something + end + end + + # bad + def foo + if /re/ === x + do_something + end + end + + # good + def foo + if x.match?(/re/) + do_something + end + end + + # good + def foo + if x =~ /re/ + do_something(Regexp.last_match) + end + end + + # good + def foo + if x.match(/re/) + do_something($~) + end + end + + # good + def foo + if /re/ === x + do_something($~) + end + end \ No newline at end of file diff --git a/config/contents/performance/start_with.md b/config/contents/performance/start_with.md index 2ab24a29..47218efa 100644 --- a/config/contents/performance/start_with.md +++ b/config/contents/performance/start_with.md @@ -7,5 +7,4 @@ This cop identifies unnecessary use of a regex where 'abc'.match(/\Aab/) # good - 'abc' =~ /ab/ - 'abc' =~ /\A\w*/ \ No newline at end of file + 'abc'.start_with?('ab') \ No newline at end of file diff --git a/config/contents/performance/unfreeze_string.md b/config/contents/performance/unfreeze_string.md new file mode 100644 index 00000000..6fae6aed --- /dev/null +++ b/config/contents/performance/unfreeze_string.md @@ -0,0 +1,20 @@ +In Ruby 2.3 or later, use unary plus operator to unfreeze a string +literal instead of `String#dup` and `String.new`. +Unary plus operator is faster than `String#dup`. + +Note: `String.new` (without operator) is not exactly the same as `+''`. +These differ in encoding. `String.new.encoding` is always `ASCII-8BIT`. +However, `(+'').encoding` is the same as script encoding(e.g. `UTF-8`). +So, if you expect `ASCII-8BIT` encoding, disable this cop. + +### Example: + # bad + ''.dup + "something".dup + String.new + String.new('') + String.new('something') + + # good + +'something' + +'' \ No newline at end of file diff --git a/config/contents/performance/uri_default_parser.md b/config/contents/performance/uri_default_parser.md new file mode 100644 index 00000000..aba62454 --- /dev/null +++ b/config/contents/performance/uri_default_parser.md @@ -0,0 +1,9 @@ +This cop identifies places where `URI::Parser.new` +can be replaced by `URI::DEFAULT_PARSER`. + +### Example: + # bad + URI::Parser.new + + # good + URI::DEFAULT_PARSER diff --git a/config/contents/rails/action_filter.md b/config/contents/rails/action_filter.md index ec40111d..d253b9d4 100644 --- a/config/contents/rails/action_filter.md +++ b/config/contents/rails/action_filter.md @@ -1,4 +1,7 @@ This cop enforces the consistent use of action filter methods. The cop is configurable and can enforce the use of the older -something_filter methods or the newer something_action methods. \ No newline at end of file +something_filter methods or the newer something_action methods. + +If the TargetRailsVersion is set to less than 4.0, the cop will enforce +the use of filter methods. \ No newline at end of file diff --git a/config/contents/rails/active_support_aliases.md b/config/contents/rails/active_support_aliases.md new file mode 100644 index 00000000..d544026f --- /dev/null +++ b/config/contents/rails/active_support_aliases.md @@ -0,0 +1,15 @@ +This cop checks that ActiveSupport aliases to core ruby methods +are not used. + +### Example: + # good + 'some_string'.start_with?('prefix') + 'some_string'.end_with?('suffix') + [1, 2, 'a'] << 'b' + [1, 2, 'a'].unshift('b') + + # bad + 'some_string'.starts_with?('prefix') + 'some_string'.ends_with?('suffix') + [1, 2, 'a'].append('b') + [1, 2, 'a'].prepend('b') diff --git a/config/contents/rails/application_job.md b/config/contents/rails/application_job.md new file mode 100644 index 00000000..0f82d5fe --- /dev/null +++ b/config/contents/rails/application_job.md @@ -0,0 +1,13 @@ +This cop checks that jobs subclass ApplicationJob with Rails 5.0. + +### Example: + + # good + class Rails5Job < ApplicationJob + ... + end + + # bad + class Rails4Job < ActiveJob::Base + ... + end \ No newline at end of file diff --git a/config/contents/rails/application_record.md b/config/contents/rails/application_record.md new file mode 100644 index 00000000..d0f39367 --- /dev/null +++ b/config/contents/rails/application_record.md @@ -0,0 +1,13 @@ +This cop checks that models subclass ApplicationRecord with Rails 5.0. + +### Example: + + # good + class Rails5Model < ApplicationRecord + ... + end + + # bad + class Rails4Model < ActiveRecord::Base + ... + end \ No newline at end of file diff --git a/config/contents/rails/blank.md b/config/contents/rails/blank.md new file mode 100644 index 00000000..96dc9c0a --- /dev/null +++ b/config/contents/rails/blank.md @@ -0,0 +1,34 @@ +This cops checks for code that can be changed to `blank?`. +Settings: + NilOrEmpty: Convert checks for `nil` or `empty?` to `blank?` + NotPresent: Convert usages of not `present?` to `blank?` + UnlessPresent: Convert usages of `unless` `present?` to `blank?` + +### Example: + # NilOrEmpty: true + # bad + foo.nil? || foo.empty? + foo == nil || foo.empty? + + # good + foo.blank? + + # NotPresent: true + # bad + !foo.present? + + # good + foo.blank? + + # UnlessPresent: true + # bad + something unless foo.present? + unless foo.present? + something + end + + # good + something if foo.blank? + if foo.blank? + something + end \ No newline at end of file diff --git a/config/contents/rails/date.md b/config/contents/rails/date.md index 33406493..9fcf60c3 100644 --- a/config/contents/rails/date.md +++ b/config/contents/rails/date.md @@ -20,7 +20,7 @@ and only 'to_time' is reported as warning. Time.zone.today Time.zone.today - 1.day - # acceptable + # flexible Date.current Date.yesterday diff --git a/config/contents/rails/delegate.md b/config/contents/rails/delegate.md index 3741c1f3..3fdb58c3 100644 --- a/config/contents/rails/delegate.md +++ b/config/contents/rails/delegate.md @@ -1,5 +1,14 @@ -This cop looks for delegations, that could have been created -automatically with delegate method. +This cop looks for delegations that could have been created +automatically with the `delegate` method. + +Safe navigation `&.` is ignored because Rails' `allow_nil` +option checks not just for nil but also delegates if nil +responds to the delegated method. + +The `EnforceForPrefixed` option (defaulted to `true`) means that +using the target object as a prefix of the method name +without using the `delegate` method will be a violation. +When set to `false`, this case is legal. ### Example: # bad @@ -10,6 +19,18 @@ automatically with delegate method. # good delegate :bar, to: :foo + # good + def bar + foo&.bar + end + + # good + private + def bar + foo.bar + end + + # EnforceForPrefixed: true # bad def foo_bar foo.bar @@ -18,8 +39,11 @@ automatically with delegate method. # good delegate :bar, to: :foo, prefix: true + # EnforceForPrefixed: false # good - private - def bar + def foo_bar foo.bar - end \ No newline at end of file + end + + # good + delegate :bar, to: :foo, prefix: true \ No newline at end of file diff --git a/config/contents/rails/file_path.md b/config/contents/rails/file_path.md new file mode 100644 index 00000000..399cc86a --- /dev/null +++ b/config/contents/rails/file_path.md @@ -0,0 +1,11 @@ +This cop is used to identify usages of file path joining process +to use `Rails.root.join` clause. + +### Example: + # bad + Rails.root.join('app/models/goober') + File.join(Rails.root, 'app/models/goober') + "#{Rails.root}/app/models/goober" + + # good + Rails.root.join('app', 'models', 'goober') \ No newline at end of file diff --git a/config/contents/rails/has_many_or_has_one_dependent.md b/config/contents/rails/has_many_or_has_one_dependent.md new file mode 100644 index 00000000..b0e59188 --- /dev/null +++ b/config/contents/rails/has_many_or_has_one_dependent.md @@ -0,0 +1,15 @@ +This cop looks for `has_many` or `has_one` associations that don't +specify a `:dependent` option. + +### Example: + # bad + class User < ActiveRecord::Base + has_many :comments + has_one :avatar + end + + # good + class User < ActiveRecord::Base + has_many :comments, dependent: :restrict_with_exception + has_one :avatar, dependent: :destroy + end \ No newline at end of file diff --git a/config/contents/rails/http_positional_arguments.md b/config/contents/rails/http_positional_arguments.md index ac8dc938..c3676a5f 100644 --- a/config/contents/rails/http_positional_arguments.md +++ b/config/contents/rails/http_positional_arguments.md @@ -1,6 +1,9 @@ -This cop is used to identify usages of http methods -like `get`, `post`, `put`, `path` without the usage of keyword arguments -in your tests and change them to use keyword arguments. +This cop is used to identify usages of http methods like `get`, `post`, +`put`, `patch` without the usage of keyword arguments in your tests and +change them to use keyword args. This cop only applies to Rails >= 5 . +If you are running Rails < 5 you should disable the +Rails/HttpPositionalArguments cop or set your TargetRailsVersion in your +.rubocop.yml file to 4.0, etc. ### Example: # bad diff --git a/config/contents/rails/not_null_column.md b/config/contents/rails/not_null_column.md index 5fab57e9..069f0cb3 100644 --- a/config/contents/rails/not_null_column.md +++ b/config/contents/rails/not_null_column.md @@ -4,7 +4,10 @@ in migration file. ### Example: # bad add_column :users, :name, :string, null: false + add_reference :products, :category, null: false # good add_column :users, :name, :string, null: true - add_column :users, :name, :string, null: false, default: '' \ No newline at end of file + add_column :users, :name, :string, null: false, default: '' + add_reference :products, :category + add_reference :products, :category, null: false, default: 1 \ No newline at end of file diff --git a/config/contents/rails/output_safety.md b/config/contents/rails/output_safety.md index 186df2f7..3a629a84 100644 --- a/config/contents/rails/output_safety.md +++ b/config/contents/rails/output_safety.md @@ -1,21 +1,64 @@ -This cop checks for the use of output safety calls like html_safe and -raw. +This cop checks for the use of output safety calls like html_safe, +raw, and safe_concat. These methods do not escape content. They +simply return a SafeBuffer containing the content as is. Instead, +use safe_join to join content and escape it and concat to +concatenate content and escape it, ensuring its safety. ### Example: + user_content = "hi" + # bad - "
#{text}
".html_safe + "#{user_content}
".html_safe + => ActiveSupport::SafeBuffer + "hi
" # good - content_tag(:p, text) + content_tag(:p, user_content) + => ActiveSupport::SafeBuffer + "<b>hi</b>
" # bad out = "" - out << content_tag(:li, "one") - out << content_tag(:li, "two") + out << "