From 4b92e19b62e06283c6dabba310f1e8206b5725e4 Mon Sep 17 00:00:00 2001 From: briri Date: Fri, 1 Oct 2021 09:58:50 -0700 Subject: [PATCH 01/84] updated rubocop and started editing .rubocop.yml --- .rubocop.yml | 446 ++++++++++++++++++++++++++++++++++----------------- Gemfile | 8 +- Gemfile.lock | 27 +--- 3 files changed, 307 insertions(+), 174 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index af6bbac1ba..151c3c1def 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,179 +1,339 @@ +# ---------------- +# - INSTRUCTIONS - +# ---------------- +# The DMPRoadmap codebase tries to follow the latest Ruby/Rails style guidelines as defined +# by the community via the Rubocop gem. +# +# Before submitting a PR, please run `bin/rubocop` from the project root. +# Note that you can specify individual files or folders e.g.: `bin/rubocop app/mailers` +# Note you can let Rubocop auto-correct many issues with the `-a` flag +# +# New versions of Rubocop typically include new Cops (Cops are inidivual Rubocop rules). +# If you see a message like the following when you run `bin/rubocop`: +# +# "The following cops were added to RuboCop, but are not configured. Please set Enabled +# to either `true` or `false` in your `.rubocop.yml` file." +# +# You should copy and paste the specified Cops into this file. You can review what the +# Cop will do by Googling the name of the rule e.g.: "rubocop Layout/SpaceBeforeBrackets" +# +# After you review the rule, you can either Enable it or Disable it in this file. The +# Rubocop documentation for the Cop may also give you additional options that can be +# configured. +# +# Try to place any new Cops under their relevant section and in alphabetical order + AllCops: - # Cache the results for faster processing - UseCache: true # Show the name of the cops being voilated in the feedback DisplayCopNames: true DisplayStyleGuide: true + + # Rubocop will skip checking the following directories Exclude: - 'bin/**/*' - 'db/**/*' - 'vendor/**/*' - 'node_modules/**/*' - - 'test/**/*' - - 'lib/tasks/*' -# Force no empty lines at the start or end of a block's body. Ignore specs, since this -# improves readability within the RSpec blocks. -Layout/EmptyLinesAroundBlockBody: - Exclude: - - 'spec/**/*' + # Automatically add any new Cops to this file and enable them + NewCops: enable -# Force a single blank line around a class's body. Adding this whitespace makes code -# a bit easier to read. -Layout/EmptyLinesAroundClassBody: - Enabled: true - EnforcedStyle: empty_lines + # Cache the results for faster processing + UseCache: true -# Force a single blank line around a module's body. Adding this whitespace makes code -# a bit easier to read. -Layout/EmptyLinesAroundModuleBody: +# ----------- +# - GEMSPEC - +# ----------- +Gemspec/DateAssignment: # new in 1.10 Enabled: true - EnforcedStyle: empty_lines -# Ignore this cop. The Rubocop default is sensible, but the rubocop-rails gem modifies -# this to position end keywords awkwardly. -Layout/EndAlignment: +# ---------- +# - LAYOUT - +# ---------- +Layout/LineEndStringConcatenationIndentation: # new in 1.18 Enabled: true - EnforcedStyleAlignWith: keyword - -# The difference between `rails` and `normal` is that the `rails` style -# prescribes that in classes and modules the `protected` and `private` -# modifier keywords shall be indented the same as public methods and that -# protected and private members shall be indented one step more than the -# modifiers. Other than that, both styles mean that entities on the same -# logical depth shall have the same indentation. -Layout/IndentationConsistency: - Description: 'Keep indentation straight.' - StyleGuide: '#spaces-indentation' - Enabled: true - EnforcedStyle: normal - -Layout/IndentationWidth: - Description: 'Use 2 spaces for indentation.' - StyleGuide: '#spaces-indentation' +Layout/SpaceBeforeBrackets: # new in 1.7 Enabled: true -# Restrict the length of each line of code to 90 characters. Enforcing this is important -# as many developers are working on smaller screens, or split screens. Having to scroll -# to read a full line of code makes code harder to read and more frustrating to work with. -Layout/LineLength: - # I've found that 90 is a suitable limit. Many developers balk at the 80 character - # default. - Max: 100 - -Layout/EmptyLinesAroundAttributeAccessor: +# -------- +# - LINT - +# -------- +Lint/AmbiguousAssignment: # new in 1.7 Enabled: true - -Layout/SpaceAroundMethodCallOperator: +Lint/AmbiguousOperatorPrecedence: # new in 1.21 Enabled: true - -# Enforce this in the main code but ignore it in specs since the Rspec core methods -# are defined as potentially ambiguous blocks -Lint/AmbiguousBlockAssociation: - Exclude: - - 'spec/**/*' - -Lint/DeprecatedOpenSSLConstant: +Lint/AmbiguousRange: # new in 1.19 Enabled: true - -Lint/MixedRegexpCaptureTypes: +Lint/DeprecatedConstants: # new in 1.8 Enabled: true - -Lint/RaiseException: +Lint/DuplicateBranch: # new in 1.3 Enabled: true - -Lint/StructNewOverride: +Lint/DuplicateRegexpCharacterClassElement: # new in 1.1 Enabled: true - -# Bumping the default AbcSize so we don't need to refactor everything -Metrics/AbcSize: - Max: 25 - -# Restrict the number of lines of code that may be within a block of code. This should -# force developers to break their code into smaller discrete methods or objects. -Metrics/BlockLength: - # Exclude specs, since those are defined as large blocks of code - Exclude: - - 'spec/**/*' - -# Bumping the default ClassLength so we don't need to refactor everything -Metrics/ClassLength: - Max: 300 - -# Bumping the default CyclomaticComplexity so we don't need to refactor everything -Metrics/CyclomaticComplexity: - Max: 25 - -# Bumping the default MethodLength so we don't need to refactor everything -Metrics/MethodLength: - Max: 25 - -# Bumping the default PerceivedComplexity so we don't need to refactor everything -Metrics/PerceivedComplexity: - Max: 25 - -# This cop enforces the use of boolean and/or "&&" and "||" over "and" "or". -# Sometimes using "and"/"or" is preferrable, when these are used as control flow. -# -# For example: -# -# render text: "Hello world" and return -# -Style/AndOr: - Enabled: false - -# This cop enforces how modules and classes are nested within another module or class. -# In Rails code (e.g. models and controllers) nesting with a colon is preferrable (e.g. -# User::Session). -Style/ClassAndModuleChildren: - Exclude: - - 'app/**/*' - -# This cop enforces each class to have documentation at the top. That's not always -# practical or necessary in Rails apps (e.g. the purpose of helpers is self evident). -Style/Documentation: - Enabled: false - -# Enforce empty methods to be written across two lines, like any normal method would be. -# This allows for easy modification of the method in future. -Style/EmptyMethod: +Lint/EmptyBlock: # new in 1.1 + Enabled: true +Lint/EmptyClass: # new in 1.3 + Enabled: true +Lint/EmptyInPattern: # new in 1.16 + Enabled: true +Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21 + Enabled: true +Lint/LambdaWithoutLiteralBlock: # new in 1.8 + Enabled: true +Lint/NoReturnInBeginEndBlocks: # new in 1.2 + Enabled: true +Lint/NumberedParameterAssignment: # new in 1.9 + Enabled: true +Lint/OrAssignmentToConstant: # new in 1.9 + Enabled: true +Lint/RedundantDirGlobSort: # new in 1.8 + Enabled: true +Lint/RequireRelativeSelfPath: # new in 1.22 + Enabled: true +Lint/SymbolConversion: # new in 1.9 + Enabled: true +Lint/ToEnumArguments: # new in 1.1 + Enabled: true +Lint/TripleQuotes: # new in 1.9 + Enabled: true +Lint/UnexpectedBlockArity: # new in 1.5 + Enabled: true +Lint/UnmodifiedReduceAccumulator: # new in 1.1 Enabled: true - EnforcedStyle: expanded -# Leave the string formatting style as `"some text %{value}" % { value: "text" }` -# since we're uncertain what effect `format` and `sprintf` may have on the Fastgetext -# markup `_("text")` -Style/FormatString: - EnforcedStyle: percent +# ----------- +# - METRICS - +# ----------- -# Prefer the use of `"some %{token} text"` instead of `some % text` or -# `some %token text` since it would invalidate many of our translation strings -Style/FormatStringToken: - EnforcedStyle: template -# Enforce double quotes. Don't allow single quotes. This is preferred since double -# quotes are more useful (they support escaping characters, and interpolation). -Style/StringLiterals: +# ------------ +# - SECURITY - +# ------------ +Security/IoMethods: # new in 1.22 Enabled: true - EnforcedStyle: double_quotes -Style/ExponentialNotation: +# --------- +# - STYLE - +# --------- +Style/ArgumentsForwarding: # new in 1.1 Enabled: true - -Style/HashEachMethods: +Style/CollectionCompact: # new in 1.2 Enabled: true - -Style/HashTransformKeys: +Style/DocumentDynamicEvalDefinition: # new in 1.1 Enabled: true - -Style/HashTransformValues: +Style/EndlessMethod: # new in 1.8 Enabled: true - -Style/RedundantRegexpCharacterClass: +Style/HashConversion: # new in 1.10 Enabled: true - -Style/RedundantRegexpEscape: +Style/HashExcept: # new in 1.7 Enabled: true - -Style/SlicingWithRange: +Style/IfWithBooleanLiteralBranches: # new in 1.9 + Enabled: true +Style/InPatternThen: # new in 1.16 + Enabled: true +Style/MultilineInPatternThen: # new in 1.16 + Enabled: true +Style/NegatedIfElseCondition: # new in 1.2 + Enabled: true +Style/NilLambda: # new in 1.3 + Enabled: true +Style/NumberedParameters: # new in 1.22 + Enabled: true +Style/NumberedParametersLimit: # new in 1.22 + Enabled: true +Style/QuotedSymbols: # new in 1.16 Enabled: true +Style/RedundantArgument: # new in 1.4 + Enabled: true +Style/RedundantSelfAssignmentBranch: # new in 1.19 + Enabled: true +Style/SelectByRegexp: # new in 1.22 + Enabled: true +Style/StringChars: # new in 1.12 + Enabled: true +Style/SwapValues: # new in 1.1 + Enabled: true + +# ================================================ +# OLD SETTINGS: +# ================================================ +# ================================================ +# AllCops: +# # Cache the results for faster processing +# UseCache: true +# # Show the name of the cops being voilated in the feedback +# DisplayCopNames: true +# DisplayStyleGuide: true +# Exclude: +# - 'bin/**/*' +# - 'db/**/*' +# - 'vendor/**/*' +# - 'node_modules/**/*' +# - 'test/**/*' +# - 'lib/tasks/*' +# +# # Force no empty lines at the start or end of a block's body. Ignore specs, since this +# # improves readability within the RSpec blocks. +# Layout/EmptyLinesAroundBlockBody: +# Exclude: +# - 'spec/**/*' +# +# # Force a single blank line around a class's body. Adding this whitespace makes code +# # a bit easier to read. +# Layout/EmptyLinesAroundClassBody: +# Enabled: true +# EnforcedStyle: empty_lines +# +# # Force a single blank line around a module's body. Adding this whitespace makes code +# # a bit easier to read. +# Layout/EmptyLinesAroundModuleBody: +# Enabled: true +# EnforcedStyle: empty_lines +# +# # Ignore this cop. The Rubocop default is sensible, but the rubocop-rails gem modifies +# # this to position end keywords awkwardly. +# Layout/EndAlignment: +# Enabled: true +# EnforcedStyleAlignWith: keyword + +# # The difference between `rails` and `normal` is that the `rails` style +# # prescribes that in classes and modules the `protected` and `private` +# # modifier keywords shall be indented the same as public methods and that +# # protected and private members shall be indented one step more than the +# # modifiers. Other than that, both styles mean that entities on the same +# # logical depth shall have the same indentation. +# Layout/IndentationConsistency: +# Description: 'Keep indentation straight.' +# StyleGuide: '#spaces-indentation' +# Enabled: true +# EnforcedStyle: normal +# +# Layout/IndentationWidth: +# Description: 'Use 2 spaces for indentation.' +# StyleGuide: '#spaces-indentation' +# Enabled: true +# +# # Restrict the length of each line of code to 90 characters. Enforcing this is important +# # as many developers are working on smaller screens, or split screens. Having to scroll +# # to read a full line of code makes code harder to read and more frustrating to work with. +# Layout/LineLength: +# # I've found that 90 is a suitable limit. Many developers balk at the 80 character +# # default. +# Max: 100 +# +# Layout/EmptyLinesAroundAttributeAccessor: +# Enabled: true +# +# Layout/SpaceAroundMethodCallOperator: +# Enabled: true +# +# # Enforce this in the main code but ignore it in specs since the Rspec core methods +# # are defined as potentially ambiguous blocks +# Lint/AmbiguousBlockAssociation: +# Exclude: +# - 'spec/**/*' +# +# Lint/DeprecatedOpenSSLConstant: +# Enabled: true +# +# Lint/MixedRegexpCaptureTypes: +# Enabled: true +# +# Lint/RaiseException: +# Enabled: true +# +# Lint/StructNewOverride: +# Enabled: true +# +# # Bumping the default AbcSize so we don't need to refactor everything +# Metrics/AbcSize: +# Max: 25 +# +# # Restrict the number of lines of code that may be within a block of code. This should +# # force developers to break their code into smaller discrete methods or objects. +# Metrics/BlockLength: +# # Exclude specs, since those are defined as large blocks of code +# Exclude: +# - 'spec/**/*' +# +# # Bumping the default ClassLength so we don't need to refactor everything +# Metrics/ClassLength: +# Max: 300 +# +# # Bumping the default CyclomaticComplexity so we don't need to refactor everything +# Metrics/CyclomaticComplexity: +# Max: 25 +# +# # Bumping the default MethodLength so we don't need to refactor everything +# Metrics/MethodLength: +# Max: 25 +# +# # Bumping the default PerceivedComplexity so we don't need to refactor everything +# Metrics/PerceivedComplexity: +# Max: 25 +# +# # This cop enforces the use of boolean and/or "&&" and "||" over "and" "or". +# # Sometimes using "and"/"or" is preferrable, when these are used as control flow. +# # +# # For example: +# # +# # render text: "Hello world" and return +# # +# Style/AndOr: +# Enabled: false +# +# # This cop enforces how modules and classes are nested within another module or class. +# # In Rails code (e.g. models and controllers) nesting with a colon is preferrable (e.g. +# # User::Session). +# Style/ClassAndModuleChildren: +# Exclude: +# - 'app/**/*' +# +# # This cop enforces each class to have documentation at the top. That's not always +# # practical or necessary in Rails apps (e.g. the purpose of helpers is self evident). +# Style/Documentation: +# Enabled: false +# +# # Enforce empty methods to be written across two lines, like any normal method would be. +# # This allows for easy modification of the method in future. +# Style/EmptyMethod: +# Enabled: true +# EnforcedStyle: expanded +# +# # Leave the string formatting style as `"some text %{value}" % { value: "text" }` +# # since we're uncertain what effect `format` and `sprintf` may have on the Fastgetext +# # markup `_("text")` +# Style/FormatString: +# EnforcedStyle: percent +# +# # Prefer the use of `"some %{token} text"` instead of `some % text` or +# # `some %token text` since it would invalidate many of our translation strings +# Style/FormatStringToken: +# EnforcedStyle: template +# +# # Enforce double quotes. Don't allow single quotes. This is preferred since double +# # quotes are more useful (they support escaping characters, and interpolation). +# Style/StringLiterals: +# Enabled: true +# EnforcedStyle: double_quotes +# +# Style/ExponentialNotation: +# Enabled: true +# +# Style/HashEachMethods: +# Enabled: true +# +# Style/HashTransformKeys: +# Enabled: true +# +# Style/HashTransformValues: +# Enabled: true +# +# Style/RedundantRegexpCharacterClass: +# Enabled: true +# +# Style/RedundantRegexpEscape: +# Enabled: true +# +# Style/SlicingWithRange: +# Enabled: true diff --git a/Gemfile b/Gemfile index 63820fd17c..5b163d171c 100644 --- a/Gemfile +++ b/Gemfile @@ -294,11 +294,9 @@ group :ci, :development do # (http://brakemanscanner.org) gem "brakeman" - # Automatic Ruby code style checking tool. - # (https://github.com/rubocop-hq/rubocop) - # Rubocop style checks for DMP Roadmap projects. - # (https://github.com/DMPRoadmap/rubocop-DMP_Roadmap) - gem "rubocop-dmp_roadmap" + # RuboCop is a Ruby code style checking and code formatting tool. It aims to enforce + # the community-driven Ruby Style Guide. + gem "rubocop" # Helper gem to require bundler-audit # (http://github.com/stewartmckee/bundle-audit) diff --git a/Gemfile.lock b/Gemfile.lock index b9d51ac32d..a541a7ec4f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -395,31 +395,6 @@ GEM unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.12.0) parser (>= 3.0.1.1) - rubocop-dmp_roadmap (1.1.2) - rubocop (>= 0.58.2) - rubocop-rails_config (>= 0.2.2) - rubocop-rspec (>= 1.27.0) - rubocop-minitest (0.15.1) - rubocop (>= 0.90, < 2.0) - rubocop-packaging (0.5.1) - rubocop (>= 0.89, < 2.0) - rubocop-performance (1.11.5) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) - rubocop-rails (2.12.2) - activesupport (>= 4.2.0) - rack (>= 1.1) - rubocop (>= 1.7.0, < 2.0) - rubocop-rails_config (1.7.3) - railties (>= 5.0) - rubocop (>= 1.19) - rubocop-ast (>= 1.0.1) - rubocop-minitest (~> 0.15) - rubocop-packaging (~> 0.5) - rubocop-performance (~> 1.11) - rubocop-rails (~> 2.0) - rubocop-rspec (2.5.0) - rubocop (~> 1.19) ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) ruby_dig (0.0.2) @@ -572,7 +547,7 @@ DEPENDENCIES rollbar rspec-collection_matchers rspec-rails - rubocop-dmp_roadmap + rubocop sass-rails sassc-rails selenium-webdriver From d7243e249e2e5a073b94732a475b21877bdf8be3 Mon Sep 17 00:00:00 2001 From: briri Date: Fri, 1 Oct 2021 10:17:35 -0700 Subject: [PATCH 02/84] added rubocop-rails and rubocop-rspec --- Gemfile | 14 +++++++++++--- Gemfile.lock | 8 ++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 5b163d171c..065e27c187 100644 --- a/Gemfile +++ b/Gemfile @@ -294,13 +294,21 @@ group :ci, :development do # (http://brakemanscanner.org) gem "brakeman" + # Helper gem to require bundler-audit + # (http://github.com/stewartmckee/bundle-audit) + gem "bundle-audit" + # RuboCop is a Ruby code style checking and code formatting tool. It aims to enforce # the community-driven Ruby Style Guide. gem "rubocop" - # Helper gem to require bundler-audit - # (http://github.com/stewartmckee/bundle-audit) - gem "bundle-audit" + # Automatic Rails code style checking tool. A RuboCop extension focused on enforcing + # Rails best practices and coding conventions. + gem "rubocop-rails" + + # Code style checking for RSpec files. A plugin for the RuboCop code style enforcing + # & linting tool. + gem "rubocop-rspec" end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index a541a7ec4f..5995cbbad2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -395,6 +395,12 @@ GEM unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.12.0) parser (>= 3.0.1.1) + rubocop-rails (2.12.2) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.7.0, < 2.0) + rubocop-rspec (2.5.0) + rubocop (~> 1.19) ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) ruby_dig (0.0.2) @@ -548,6 +554,8 @@ DEPENDENCIES rspec-collection_matchers rspec-rails rubocop + rubocop-rails + rubocop-rspec sass-rails sassc-rails selenium-webdriver From 9b13616b939dec8bf5fa36fb4dbc3823b49f7b6f Mon Sep 17 00:00:00 2001 From: briri Date: Fri, 1 Oct 2021 10:29:12 -0700 Subject: [PATCH 03/84] added some additional rubocop helper gems --- Gemfile | 7 +++++++ Gemfile.lock | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/Gemfile b/Gemfile index 065e27c187..66f5eb8818 100644 --- a/Gemfile +++ b/Gemfile @@ -302,6 +302,13 @@ group :ci, :development do # the community-driven Ruby Style Guide. gem "rubocop" + # RuboCop rules for detecting and autocorrecting undecorated strings for i18n + # (gettext and rails-i18n) + gem "rubocop-i18n" + + # A collection of RuboCop cops to check for performance optimizations in Ruby code. + gem "rubocop-performance" + # Automatic Rails code style checking tool. A RuboCop extension focused on enforcing # Rails best practices and coding conventions. gem "rubocop-rails" diff --git a/Gemfile.lock b/Gemfile.lock index 5995cbbad2..c9a277d4d4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -395,6 +395,11 @@ GEM unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.12.0) parser (>= 3.0.1.1) + rubocop-i18n (3.0.0) + rubocop (~> 1.0) + rubocop-performance (1.11.5) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) rubocop-rails (2.12.2) activesupport (>= 4.2.0) rack (>= 1.1) @@ -554,6 +559,8 @@ DEPENDENCIES rspec-collection_matchers rspec-rails rubocop + rubocop-i18n + rubocop-performance rubocop-rails rubocop-rspec sass-rails From f6dfc665cae170ba70e2e0c94fedfa60917bfaf9 Mon Sep 17 00:00:00 2001 From: briri Date: Fri, 1 Oct 2021 10:37:22 -0700 Subject: [PATCH 04/84] added some additional rubocop helper gems --- Gemfile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Gemfile b/Gemfile index 66f5eb8818..0ead3831fa 100644 --- a/Gemfile +++ b/Gemfile @@ -313,9 +313,17 @@ group :ci, :development do # Rails best practices and coding conventions. gem "rubocop-rails" + # A RuboCop plugin for Rake tasks + gem "rubocop-rake" + # Code style checking for RSpec files. A plugin for the RuboCop code style enforcing # & linting tool. gem "rubocop-rspec" + + # Thread-safety checks via static analysis. A plugin for the RuboCop code style + # enforcing & linting tool. + gem "rubocop-thread_safety" + end group :development do From cf7ed3bf9e25e3261393b990cbebf70cd9ee03a8 Mon Sep 17 00:00:00 2001 From: briri Date: Fri, 1 Oct 2021 10:38:02 -0700 Subject: [PATCH 05/84] added some additional rubocop helper gems --- Gemfile.lock | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Gemfile.lock b/Gemfile.lock index c9a277d4d4..b0587e2fa5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -404,8 +404,12 @@ GEM activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.7.0, < 2.0) + rubocop-rake (0.6.0) + rubocop (~> 1.0) rubocop-rspec (2.5.0) rubocop (~> 1.19) + rubocop-thread_safety (0.4.4) + rubocop (>= 0.53.0) ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) ruby_dig (0.0.2) @@ -562,7 +566,9 @@ DEPENDENCIES rubocop-i18n rubocop-performance rubocop-rails + rubocop-rake rubocop-rspec + rubocop-thread_safety sass-rails sassc-rails selenium-webdriver From 3922375c63b6d3c2efec24fce40c2e1d8b8c6cbe Mon Sep 17 00:00:00 2001 From: briri Date: Mon, 4 Oct 2021 15:58:51 -0700 Subject: [PATCH 06/84] ran Inspecting 529 files ...............................................................................CCCCCCCCC.CC.CCCCCCC.CCCCCCCCCC...CC.CCCCCC..CCC.CCCCC....CCWCCCCCCCCCCCCC.CC................................................CCCCCCCCCCCCC.CC..CCCCCCCCCCCCCCC..CCCCCCC...........................CC...C.C.........C.....C.C..........CW...CCCCCCCC.CCC.CC.CWWCCCWWW..CCCCWCCCCCCCCC...............CC.CWC.C...C...C...CWCCCCWW...C.C.CCCCCCCWCCCCC.C..CCCCC.CCCCW.CCC..CCWCCCCC.CWCC..CCC.CC.C.CCCC.CCCCCCCCCCCCCC.CCCCCCCCC.CCCCC.C....C..C..........CC...C.C.CCC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Offenses: app/helpers/annotations_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module AnnotationsHelper. module AnnotationsHelper ^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/application_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module ApplicationHelper. module ApplicationHelper ^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/application_helper.rb:22:26: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use exact_match: false instead of exact_match = false. (https://rubystyle.guide#boolean-keyword-arguments) def active_page?(path, exact_match = false) ^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:6:1: C: Style/Documentation: Missing top-level documentation comment for module ConditionsHelper. module ConditionsHelper ^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:10:5: C: [Correctable] Style/CaseLikeIf: Convert if-elsif to case-when. (https://rubystyle.guide#case-vs-if-else) if object.is_a?(Plan) ... ^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:26:3: C: Metrics/AbcSize: Assignment Branch Condition size for answer_remove_list is too high. [<7, 21, 9> 23.9/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def answer_remove_list(answer, user = nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:26:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for answer_remove_list is too high. [8/7] def answer_remove_list(answer, user = nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:26:3: C: Metrics/PerceivedComplexity: Perceived complexity for answer_remove_list is too high. [9/8] def answer_remove_list(answer, user = nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:52:3: C: Metrics/AbcSize: Assignment Branch Condition size for email_trigger_list is too high. [<5, 17, 7> 19.05/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def email_trigger_list(answer) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:84:3: C: Metrics/AbcSize: Assignment Branch Condition size for num_section_questions is too high. [<8, 22, 11> 25.87/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def num_section_questions(plan, section, phase = nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:84:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for num_section_questions is too high. [9/7] def num_section_questions(plan, section, phase = nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:84:3: C: Metrics/PerceivedComplexity: Perceived complexity for num_section_questions is too high. [9/8] def num_section_questions(plan, section, phase = nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:137:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for later_question_list is too high. [12/7] def later_question_list(question) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:137:3: C: Metrics/MethodLength: Method has too many lines. [21/20] (https://rubystyle.guide#short-methods) def later_question_list(question) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:137:3: C: Metrics/PerceivedComplexity: Perceived complexity for later_question_list is too high. [13/8] def later_question_list(question) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:170:9: C: Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) raw 'Qn. ' + question.number.to_s + ': ' + ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:178:9: C: Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) raw 'Sec. ' + section.number.to_s + ': ' + ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:188:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for condition_to_text is too high. [8/7] def condition_to_text(conditions) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:188:3: C: Metrics/PerceivedComplexity: Perceived complexity for condition_to_text is too high. [9/8] def condition_to_text(conditions) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:193:24: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) return_string += '
' + _('Answering') + ' ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:200:40: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) rems = remove_data.map { |rem| '"' + Question.find(rem).text + '"' } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:207:5: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) return_string + '
' ^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:212:5: C: [Correctable] Style/CaseLikeIf: Convert if-elsif to case-when. (https://rubystyle.guide#case-vs-if-else) if object.is_a?(Integer) # when remove question id ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:226:3: C: Metrics/AbcSize: Assignment Branch Condition size for conditions_to_param_form is too high. [<6, 19, 7> 21.12/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def conditions_to_param_form(conditions) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:226:3: C: Metrics/MethodLength: Method has too many lines. [22/20] (https://rubystyle.guide#short-methods) def conditions_to_param_form(conditions) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/conditions_helper.rb:229:15: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) title = 'condition' + condition[:number].to_s ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/customizable_template_link_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module CustomizableTemplateLinkHelper. module CustomizableTemplateLinkHelper ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/customizable_template_link_helper.rb:6:3: C: Metrics/AbcSize: Assignment Branch Condition size for link_to_customizable_template is too high. [<4, 19, 9> 21.4/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def link_to_customizable_template(name, customization, template) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/customizable_template_link_helper.rb:6:3: C: Metrics/PerceivedComplexity: Perceived complexity for link_to_customizable_template is too high. [9/8] def link_to_customizable_template(name, customization, template) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/exports_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module ExportsHelper. module ExportsHelper ^^^^^^^^^^^^^^^^^^^^ app/helpers/feedbacks_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module FeedbacksHelper. module FeedbacksHelper ^^^^^^^^^^^^^^^^^^^^^^ app/helpers/feedbacks_helper.rb:5:8: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). _('%{application_name}: Your plan has been submitted for feedback') ^^^^^^^^^^^^^^^^^^^ app/helpers/feedbacks_helper.rb:9:17: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). _('

Hello %{user_name}.

'\ ^^^^^^^^^^^^ app/helpers/feedbacks_helper.rb:10:23: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). "

Your plan \"%{plan_name}\" has been submitted for feedback from an ^^^^^^^^^^^^ app/helpers/feedbacks_helper.rb:13:10: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). at %{organisation_email}.

") ^^^^^^^^^^^^^^^^^^^^^ app/helpers/identifier_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module IdentifierHelper. module IdentifierHelper ^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/identifier_helper.rb:8:33: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) prefix = with_scheme_name ? id.identifier_scheme.description + ': ' : '' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/languages_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module LanguagesHelper. module LanguagesHelper ^^^^^^^^^^^^^^^^^^^^^^ app/helpers/mailer_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module MailerHelper. module MailerHelper ^^^^^^^^^^^^^^^^^^^ app/helpers/notifications_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module NotificationsHelper. module NotificationsHelper ^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/orgs_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module OrgsHelper. module OrgsHelper ^^^^^^^^^^^^^^^^^ app/helpers/orgs_helper.rb:13:40: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). format(_("

A data librarian from %{org_name} will respond to your request within 48 ^^^^^^^^^^^ app/helpers/orgs_helper.rb:15:11: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). at %{organisation_email}.

"), organisation_email: email, org_name: org.name) ^^^^^^^^^^^^^^^^^^^^^ app/helpers/perms_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module PermsHelper. module PermsHelper ^^^^^^^^^^^^^^^^^^ app/helpers/plans_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module PlansHelper. module PlansHelper ^^^^^^^^^^^^^^^^^^ app/helpers/sections_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module SectionsHelper. module SectionsHelper ^^^^^^^^^^^^^^^^^^^^^ app/helpers/settings_template_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module SettingsTemplateHelper. module SettingsTemplateHelper ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/settings_template_helper.rb:5:3: C: Metrics/AbcSize: Assignment Branch Condition size for admin_field_t is too high. [<0, 12, 19> 22.47/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def admin_field_t(admin_field) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/settings_template_helper.rb:5:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for admin_field_t is too high. [11/7] def admin_field_t(admin_field) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/settings_template_helper.rb:5:3: C: Metrics/PerceivedComplexity: Perceived complexity for admin_field_t is too high. [11/8] def admin_field_t(admin_field) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/super_admin/orgs/merge_helper.rb:5:5: C: Style/Documentation: Missing top-level documentation comment for module SuperAdmin::Orgs::MergeHelper. module MergeHelper ^^^^^^^^^^^^^^^^^^ app/helpers/super_admin/orgs/merge_helper.rb:17:7: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for column_content is too high. [14/7] def column_content(entries:, orcid:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/super_admin/orgs/merge_helper.rb:17:7: C: Metrics/PerceivedComplexity: Perceived complexity for column_content is too high. [9/8] def column_content(entries:, orcid:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/super_admin/orgs/merge_helper.rb:28:44: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). format(_('Guidance for: %{themes}'), themes: entry.themes.collect(&:title).join(', ')) ^^^^^^^^^ app/helpers/super_admin/orgs/merge_helper.rb:50:43: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). html = format(_("

The following %{object_types} will be moved over to '%{org_name}':

"), ^^^^^^^^^^^^^^^ app/helpers/super_admin/orgs/merge_helper.rb:50:82: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). html = format(_("

The following %{object_types} will be moved over to '%{org_name}':

"), ^^^^^^^^^^^ app/helpers/template_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module TemplateHelper. module TemplateHelper ^^^^^^^^^^^^^^^^^^^^^ app/helpers/template_helper.rb:36:3: C: Metrics/AbcSize: Assignment Branch Condition size for direct_link is too high. [<3, 18, 10> 20.81/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def direct_link(template, hidden = false, text = nil, id = nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/template_helper.rb:36:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for direct_link is too high. [10/7] def direct_link(template, hidden = false, text = nil, id = nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/template_helper.rb:36:3: C: Metrics/PerceivedComplexity: Perceived complexity for direct_link is too high. [11/8] def direct_link(template, hidden = false, text = nil, id = nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/template_helper.rb:36:29: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use hidden: false instead of hidden = false. (https://rubystyle.guide#boolean-keyword-arguments) def direct_link(template, hidden = false, text = nil, id = nil) ^^^^^^^^^^^^^^ app/helpers/usage_helper.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module UsageHelper. module UsageHelper ^^^^^^^^^^^^^^^^^^ app/helpers/usage_helper.rb:17:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for prep_data_for_template_plans_chart is too high. [12/7] def prep_data_for_template_plans_chart(data:, subset: 'by_template') ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/usage_helper.rb:17:3: C: Metrics/MethodLength: Method has too many lines. [25/20] (https://rubystyle.guide#short-methods) def prep_data_for_template_plans_chart(data:, subset: 'by_template') ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/usage_helper.rb:17:3: C: Metrics/PerceivedComplexity: Perceived complexity for prep_data_for_template_plans_chart is too high. [12/8] def prep_data_for_template_plans_chart(data:, subset: 'by_template') ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/helpers/usage_helper.rb:59:3: C: Metrics/AbcSize: Assignment Branch Condition size for plans_per_template_ranges is too high. [<0, 20, 0> 20/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def plans_per_template_ranges ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/mailers/user_mailer.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class UserMailer. class UserMailer < ActionMailer::Base ^^^^^^^^^^^^^^^^ app/mailers/user_mailer.rb:12:3: C: Metrics/AbcSize: Assignment Branch Condition size for welcome_notification is too high. [<4, 17, 1> 17.49/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def welcome_notification(user) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/mailers/user_mailer.rb:15:62: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). @email_subject = format(_('Query or feedback related to %{tool_name}'), tool_name: tool_name) ^^^^^^^^^^^^ app/mailers/user_mailer.rb:22:42: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('Welcome to %{tool_name}'), tool_name: tool_name)) ^^^^^^^^^^^^ app/mailers/user_mailer.rb:26:3: C: Metrics/AbcSize: Assignment Branch Condition size for question_answered is too high. [<10, 21, 0> 23.26/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def question_answered(data, user, answer, _options_string) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/mailers/user_mailer.rb:54:57: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('A Data Management Plan in %{tool_name} has been shared with you'), tool_name: tool_name)) ^^^^^^^^^^^^ app/mailers/user_mailer.rb:69:80: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('Changed permissions on a Data Management Plan in %{tool_name}'), tool_name: tool_name)) ^^^^^^^^^^^^ app/mailers/user_mailer.rb:82:63: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('Permissions removed on a DMP in %{tool_name}'), tool_name: tool_name)) ^^^^^^^^^^^^ app/mailers/user_mailer.rb:98:31: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('%{user_name} has requested feedback on a %{tool_name} plan'), tool_name: tool_name, ^^^^^^^^^^^^ app/mailers/user_mailer.rb:98:72: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('%{user_name} has requested feedback on a %{tool_name} plan'), tool_name: tool_name, ^^^^^^^^^^^^ app/mailers/user_mailer.rb:99:121: C: Layout/LineLength: Line is too long. [122/120] (https://rubystyle.guide#max-line-length) user_name: @user.name(false))) ^^ app/mailers/user_mailer.rb:103:3: C: Metrics/AbcSize: Assignment Branch Condition size for feedback_complete is too high. [<7, 22, 2> 23.17/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def feedback_complete(recipient, plan, requestor) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/mailers/user_mailer.rb:119:31: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('%{tool_name}: Expert feedback has been provided for %{plan_title}'), ^^^^^^^^^^^^ app/mailers/user_mailer.rb:119:83: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('%{tool_name}: Expert feedback has been provided for %{plan_title}'), ^^^^^^^^^^^^^ app/mailers/user_mailer.rb:135:55: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('DMP Visibility Changed: %{plan_title}'), plan_title: @plan.title)) ^^^^^^^^^^^^^ app/mailers/user_mailer.rb:163:31: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('%{tool_name}: A new comment was added to %{plan_title}'), tool_name: tool_name, ^^^^^^^^^^^^ app/mailers/user_mailer.rb:163:72: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('%{tool_name}: A new comment was added to %{plan_title}'), tool_name: tool_name, ^^^^^^^^^^^^^ app/mailers/user_mailer.rb:178:67: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('Administrator privileges granted in %{tool_name}'), tool_name: tool_name)) ^^^^^^^^^^^^ app/mailers/user_mailer.rb:182:3: C: Metrics/AbcSize: Assignment Branch Condition size for api_credentials is too high. [<3, 18, 2> 18.36/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def api_credentials(api_client) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/mailers/user_mailer.rb:192:31: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). subject: format(_('%{tool_name} API changes'), tool_name: tool_name)) ^^^^^^^^^^^^ app/models/annotation.rb:28:1: C: Style/Documentation: Missing top-level documentation comment for class Annotation. class Annotation < ApplicationRecord ^^^^^^^^^^^^^^^^ app/models/answer.rb:31:1: C: Style/Documentation: Missing top-level documentation comment for class Answer. class Answer < ApplicationRecord ^^^^^^^^^^^^ app/models/api_client.rb:27:1: C: Style/Documentation: Missing top-level documentation comment for class ApiClient. class ApiClient < ApplicationRecord ^^^^^^^^^^^^^^^ app/models/application_record.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class ApplicationRecord. class ApplicationRecord < ActiveRecord::Base ^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/acts_as_sortable.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module ActsAsSortable. module ActsAsSortable ^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/acts_as_sortable.rb:6:3: C: Style/Documentation: Missing top-level documentation comment for module ActsAsSortable::ClassMethods. module ClassMethods ^^^^^^^^^^^^^^^^^^^ app/models/concerns/date_rangeable.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module DateRangeable. module DateRangeable ^^^^^^^^^^^^^^^^^^^^ app/models/concerns/date_rangeable.rb:6:3: C: Style/Documentation: Missing top-level documentation comment for module DateRangeable::ClassMethods. module ClassMethods ^^^^^^^^^^^^^^^^^^^ app/models/concerns/date_rangeable.rb:17:23: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). query = format('%{table}.%{field} BETWEEN ? AND ?', table: table_name, field: field) ^^^^^^^^ app/models/concerns/date_rangeable.rb:17:32: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). query = format('%{table}.%{field} BETWEEN ? AND ?', table: table_name, field: field) ^^^^^^^^ app/models/concerns/exportable_plan.rb:10:20: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use coversheet: false instead of coversheet = false. (https://rubystyle.guide#boolean-keyword-arguments) def as_pdf(user, coversheet = false) ^^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:15:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for as_csv is too high. [15/7] def as_csv(user, ... ^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:15:3: C: Metrics/MethodLength: Method has too many lines. [23/20] (https://rubystyle.guide#short-methods) def as_csv(user, ... ^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:15:3: C: Metrics/PerceivedComplexity: Perceived complexity for as_csv is too high. [16/8] def as_csv(user, ... ^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:16:14: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use headings: true instead of headings = true. (https://rubystyle.guide#boolean-keyword-arguments) headings = true, ^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:17:14: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use unanswered: true instead of unanswered = true. (https://rubystyle.guide#boolean-keyword-arguments) unanswered = true, ^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:19:14: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use show_custom_sections: true instead of show_custom_sections = true. (https://rubystyle.guide#boolean-keyword-arguments) show_custom_sections = true, ^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:20:14: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use show_coversheet: false instead of show_coversheet = false. (https://rubystyle.guide#boolean-keyword-arguments) show_coversheet = false) ^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:55:21: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use coversheet: false instead of coversheet = false. (https://rubystyle.guide#boolean-keyword-arguments) def prepare(user, coversheet = false) ^^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:95:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for prepare_coversheet is too high. [9/7] def prepare_coversheet ... ^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:95:3: C: Metrics/PerceivedComplexity: Perceived complexity for prepare_coversheet is too high. [9/8] def prepare_coversheet ... ^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:128:3: C: Metrics/PerceivedComplexity: Perceived complexity for prepare_coversheet_for_csv is too high. [9/8] def prepare_coversheet_for_csv(csv, _headings, hash) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:133:28: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). end, format(_('%{authors}'), authors: hash[:attribution].join(', '))] ^^^^^^^^^^ app/models/concerns/exportable_plan.rb:134:40: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). csv << ['Affiliation: ', format(_('%{affiliation}'), affiliation: hash[:affiliation])] ^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:136:42: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). [_('Template: '), format(_('%{funder}'), funder: hash[:funder])] ^^^^^^^^^ app/models/concerns/exportable_plan.rb:138:42: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). [_('Template: '), format(_('%{template}'), template: hash[:template] + hash[:customizer])] ^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:140:44: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). csv << [_('Grant number: '), format(_('%{grant_number}'), grant_number: grant&.value)] if grant&.value.present? ^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:142:50: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). csv << [_('Project abstract: '), format(_('%{description}'), description: Nokogiri::HTML(description).text)] ^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:144:45: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). csv << [_('Last modified: '), format(_('%{date}'), date: updated_at.to_date.strftime('%d-%m-%Y'))] ^^^^^^^ app/models/concerns/exportable_plan.rb:159:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for show_section_for_csv is too high. [11/7] def show_section_for_csv(csv, phase, section, headings, unanswered, hash) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:159:3: C: Metrics/PerceivedComplexity: Perceived complexity for show_section_for_csv is too high. [15/8] def show_section_for_csv(csv, phase, section, headings, unanswered, hash) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/exportable_plan.rb:195:3: C: Metrics/AbcSize: Assignment Branch Condition size for record_plan_export is too high. [<8, 16, 2> 18/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def record_plan_export(user, format) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/identifiable.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module Identifiable. module Identifiable ^^^^^^^^^^^^^^^^^^^ app/models/concerns/identifiable.rb:27:5: C: Metrics/AbcSize: Assignment Branch Condition size for from_identifiers is too high. [<4, 19, 8> 21/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def self.from_identifiers(array:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/identifiable.rb:27:5: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for from_identifiers is too high. [9/7] def self.from_identifiers(array:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/identifiable.rb:27:5: C: Metrics/PerceivedComplexity: Perceived complexity for from_identifiers is too high. [9/8] def self.from_identifiers(array:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/concerns/json_link_validator.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module JSONLinkValidator. module JSONLinkValidator ^^^^^^^^^^^^^^^^^^^^^^^^ app/models/condition.rb:27:1: C: Style/Documentation: Missing top-level documentation comment for class Condition. class Condition < ApplicationRecord ^^^^^^^^^^^^^^^ app/models/contributor.rb:29:1: C: Style/Documentation: Missing top-level documentation comment for class Contributor. class Contributor < ApplicationRecord ^^^^^^^^^^^^^^^^^ app/models/contributor.rb:98:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for == is too high. [8/7] def ==(other) ... ^^^^^^^^^^^^^ app/models/contributor.rb:111:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for merge is too high. [11/7] def merge(other) ... ^^^^^^^^^^^^^^^^ app/models/contributor.rb:111:3: C: Metrics/PerceivedComplexity: Perceived complexity for merge is too high. [11/8] def merge(other) ... ^^^^^^^^^^^^^^^^ app/models/exported_plan.rb:109:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for as_csv is too high. [12/7] def as_csv(sections, unanswered_questions, question_headings) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/exported_plan.rb:109:3: C: Metrics/PerceivedComplexity: Perceived complexity for as_csv is too high. [15/8] def as_csv(sections, unanswered_questions, question_headings) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/exported_plan.rb:159:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for as_txt is too high. [14/7] def as_txt(sections, unanswered_questions, question_headings, details) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/exported_plan.rb:159:3: C: Metrics/PerceivedComplexity: Perceived complexity for as_txt is too high. [17/8] def as_txt(sections, unanswered_questions, question_headings, details) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/exported_plan.rb:161:15: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) output += "\n" + _('Details') + "\n\n" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/exported_plan.rb:166:21: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) admin_field_t(at.to_s) + ': ' + value + "\n" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/exported_plan.rb:168:21: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) admin_field_t(at.to_s) + ': ' + _('-') + "\n" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/exported_plan.rb:185:21: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) output += _('Question not answered.') + "\n" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/exported_plan.rb:208:22: C: [Correctable] Style/CaseLikeIf: Convert if-elsif to case-when. (https://rubystyle.guide#case-vs-if-else) if question_settings == :all ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/guidance.rb:36:1: C: Style/Documentation: Missing top-level documentation comment for class Guidance. class Guidance < ApplicationRecord ^^^^^^^^^^^^^^ app/models/guidance.rb:86:3: C: Metrics/AbcSize: Assignment Branch Condition size for can_view? is too high. [<5, 17, 6> 18.71/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def self.can_view?(user, id) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/guidance_group.rb:27:1: C: Style/Documentation: Missing top-level documentation comment for class GuidanceGroup. class GuidanceGroup < ApplicationRecord ^^^^^^^^^^^^^^^^^^^ app/models/guidance_group.rb:139:3: C: Metrics/AbcSize: Assignment Branch Condition size for merge! is too high. [<1, 19, 4> 19.44/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def merge!(to_be_merged:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/identifier.rb:69:3: C: Metrics/AbcSize: Assignment Branch Condition size for value= is too high. [<2, 17, 6> 18.14/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def value=(val) ... ^^^^^^^^^^^^^^^ app/models/identifier_scheme.rb:18:1: C: Style/Documentation: Missing top-level documentation comment for class IdentifierScheme. class IdentifierScheme < ApplicationRecord ^^^^^^^^^^^^^^^^^^^^^^ app/models/language.rb:14:1: C: Style/Documentation: Missing top-level documentation comment for class Language. class Language < ApplicationRecord ^^^^^^^^^^^^^^ app/models/notification.rb:20:1: C: Style/Documentation: Missing top-level documentation comment for class Notification. class Notification < ApplicationRecord ^^^^^^^^^^^^^^^^^^ app/models/org.rb:234:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for org_type_to_s is too high. [8/7] def org_type_to_s ... ^^^^^^^^^^^^^^^^^ app/models/org.rb:284:3: C: Metrics/AbcSize: Assignment Branch Condition size for org_admin_plans is too high. [<1, 21, 2> 21.12/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def org_admin_plans ... ^^^^^^^^^^^^^^^^^^^ app/models/org.rb:355:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for merge_attributes! is too high. [13/7] def merge_attributes!(to_be_merged:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/org.rb:355:3: C: Metrics/PerceivedComplexity: Perceived complexity for merge_attributes! is too high. [13/8] def merge_attributes!(to_be_merged:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/org.rb:370:3: C: Metrics/AbcSize: Assignment Branch Condition size for merge_departments! is too high. [<3, 19, 6> 20.15/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def merge_departments!(to_be_merged:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/perm.rb:13:1: C: Style/Documentation: Missing top-level documentation comment for class Perm. class Perm < ApplicationRecord ^^^^^^^^^^ app/models/plan.rb:43:1: C: Style/Documentation: Missing top-level documentation comment for class Plan. class Plan < ApplicationRecord ^^^^^^^^^^ app/models/plan.rb:236:3: C: Metrics/AbcSize: Assignment Branch Condition size for deep_copy is too high. [<7, 16, 3> 17.72/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def self.deep_copy(plan) ... ^^^^^^^^^^^^^^^^^^^^^^^^ app/models/plan.rb:280:3: C: Metrics/AbcSize: Assignment Branch Condition size for answer is too high. [<12, 20, 7> 24.35/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def answer(qid, create_if_missing = true) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/plan.rb:280:19: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use create_if_missing: true instead of create_if_missing = true. (https://rubystyle.guide#boolean-keyword-arguments) def answer(qid, create_if_missing = true) ^^^^^^^^^^^^^^^^^^^^^^^^ app/models/plan.rb:367:3: C: Metrics/AbcSize: Assignment Branch Condition size for readable_by? is too high. [<1, 17, 8> 18.81/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def readable_by?(user_id) ... ^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/plan.rb:367:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for readable_by? is too high. [8/7] def readable_by?(user_id) ... ^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/plan.rb:367:3: C: Metrics/PerceivedComplexity: Perceived complexity for readable_by? is too high. [9/8] def readable_by?(user_id) ... ^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/plan.rb:577:3: C: Metrics/AbcSize: Assignment Branch Condition size for grant= is too high. [<4, 15, 8> 17.46/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def grant=(params) ... ^^^^^^^^^^^^^^^^^^ app/models/plan.rb:577:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for grant= is too high. [8/7] def grant=(params) ... ^^^^^^^^^^^^^^^^^^ app/models/pref.rb:12:1: C: Style/Documentation: Missing top-level documentation comment for class Pref. class Pref < ApplicationRecord ^^^^^^^^^^ app/models/question.rb:140:3: C: Metrics/AbcSize: Assignment Branch Condition size for guidance_for_org is too high. [<5, 19, 5> 20.27/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def guidance_for_org(org) ... ^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/question.rb:259:3: C: Metrics/AbcSize: Assignment Branch Condition size for check_remove_conditions is too high. [<3, 16, 6> 17.35/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def check_remove_conditions ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/question_format.rb:16:1: C: Style/Documentation: Missing top-level documentation comment for class QuestionFormat. class QuestionFormat < ApplicationRecord ^^^^^^^^^^^^^^^^^^^^ app/models/question_option.rb:24:1: C: Style/Documentation: Missing top-level documentation comment for class QuestionOption. class QuestionOption < ApplicationRecord ^^^^^^^^^^^^^^^^^^^^ app/models/role.rb:26:1: C: Style/Documentation: Missing top-level documentation comment for class Role. class Role < ApplicationRecord ^^^^^^^^^^ app/models/section.rb:27:1: C: Style/Documentation: Missing top-level documentation comment for class Section. class Section < ApplicationRecord ^^^^^^^^^^^^^ app/models/section_sorter.rb:31:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for sort! is too high. [17/7] def sort! ... ^^^^^^^^^ app/models/section_sorter.rb:31:3: C: Metrics/PerceivedComplexity: Perceived complexity for sort! is too high. [19/8] def sort! ... ^^^^^^^^^ app/models/section_sorter.rb:34:5: W: Lint/DuplicateBranch: Duplicate branch body detected. elsif all_sections_modifiable? ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/settings/template.rb:17:3: C: Style/Documentation: Missing top-level documentation comment for class Settings::Template. class Template < RailsSettings::SettingObject ^^^^^^^^^^^^^^ app/models/settings/template.rb:77:11: C: [Correctable] Style/CaseLikeIf: Convert if-elsif to case-when. (https://rubystyle.guide#case-vs-if-else) if key == :missing_key ... ^^^^^^^^^^^^^^^^^^^^^^ app/models/settings/template.rb:104:39: C: [Correctable] Style/AndOr: Use || instead of or. (https://rubystyle.guide#no-and-or-or) unless formatting[:margin].nil? or !formatting[:margin].is_a?(Hash) ^^ app/models/stat.rb:18:1: C: Style/Documentation: Missing top-level documentation comment for class Stat. class Stat < ApplicationRecord ^^^^^^^^^^ app/models/stat_created_plan.rb:20:1: C: Style/Documentation: Missing top-level documentation comment for class StatCreatedPlan. class StatCreatedPlan < Stat ^^^^^^^^^^^^^^^^^^^^^ app/models/stat_created_plan.rb:52:5: C: Metrics/AbcSize: Assignment Branch Condition size for to_csv_by_template is too high. [<14, 22, 7> 27/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def to_csv_by_template(created_plans, sep = ',') ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/stat_created_plan.rb:52:5: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for to_csv_by_template is too high. [8/7] def to_csv_by_template(created_plans, sep = ',') ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/stat_created_plan.rb:52:5: C: Metrics/MethodLength: Method has too many lines. [21/20] (https://rubystyle.guide#short-methods) def to_csv_by_template(created_plans, sep = ',') ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/stat_created_plan/create_or_update.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class StatCreatedPlan::CreateOrUpdate. class CreateOrUpdate ^^^^^^^^^^^^^^^^^^^^ app/models/stat_created_plan/create_or_update.rb:6:7: C: Metrics/MethodLength: Method has too many lines. [23/20] (https://rubystyle.guide#short-methods) def do(start_date:, end_date:, org:, filtered: false) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/stat_exported_plan.rb:18:1: C: Style/Documentation: Missing top-level documentation comment for class StatExportedPlan. class StatExportedPlan < Stat ^^^^^^^^^^^^^^^^^^^^^^ app/models/stat_exported_plan/create_or_update.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class StatExportedPlan::CreateOrUpdate. class CreateOrUpdate ^^^^^^^^^^^^^^^^^^^^ app/models/stat_joined_user.rb:18:1: C: Style/Documentation: Missing top-level documentation comment for class StatJoinedUser. class StatJoinedUser < Stat ^^^^^^^^^^^^^^^^^^^^ app/models/stat_joined_user/create_or_update.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class StatJoinedUser::CreateOrUpdate. class CreateOrUpdate ^^^^^^^^^^^^^^^^^^^^ app/models/stat_shared_plan.rb:18:1: C: Style/Documentation: Missing top-level documentation comment for class StatSharedPlan. class StatSharedPlan < Stat ^^^^^^^^^^^^^^^^^^^^ app/models/stat_shared_plan/create_or_update.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class StatSharedPlan::CreateOrUpdate. class CreateOrUpdate ^^^^^^^^^^^^^^^^^^^^ app/models/template.rb:279:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for deep_copy is too high. [12/7] def deep_copy(attributes: {}, **options) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/template.rb:279:3: C: Metrics/MethodLength: Method has too many lines. [23/20] (https://rubystyle.guide#short-methods) def deep_copy(attributes: {}, **options) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/template.rb:279:3: C: Metrics/PerceivedComplexity: Perceived complexity for deep_copy is too high. [12/8] def deep_copy(attributes: {}, **options) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/template.rb:379:34: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). title: format(_('Copy of %{template}'), template: title) ^^^^^^^^^^^ app/models/template.rb:433:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for publishability is too high. [13/7] def publishability ... ^^^^^^^^^^^^^^^^^^ app/models/template.rb:433:3: C: Metrics/PerceivedComplexity: Perceived complexity for publishability is too high. [13/8] def publishability ... ^^^^^^^^^^^^^^^^^^ app/models/template.rb:451:88: C: [Correctable] Style/AndOr: Use && instead of and. (https://rubystyle.guide#no-and-or-or) unless phases.map { |p| p.sections.count.positive? }.reduce(true) { |fin, val| fin and val } ^^^ app/models/template.rb:456:91: C: [Correctable] Style/AndOr: Use && instead of and. (https://rubystyle.guide#no-and-or-or) unless sections.map { |s| s.questions.count.positive? }.reduce(true) { |fin, val| fin and val } ^^^ app/models/theme.rb:15:1: C: Style/Documentation: Missing top-level documentation comment for class Theme. class Theme < ApplicationRecord ^^^^^^^^^^^ app/models/token_permission_type.rb:14:1: C: Style/Documentation: Missing top-level documentation comment for class TokenPermissionType. class TokenPermissionType < ApplicationRecord ^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/user.rb:218:12: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use use_email: true instead of use_email = true. (https://rubystyle.guide#boolean-keyword-arguments) def name(use_email = true) ^^^^^^^^^^^^^^^^ app/models/user.rb:248:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for can_org_admin? is too high. [8/7] def can_org_admin? ... ^^^^^^^^^^^^^^^^^^ app/models/user.rb:380:44: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). '%{application_name} has been shared with you'), application_name: ApplicationService.application_name)) ^^^^^^^^^^^^^^^^^^^ app/models/user.rb:380:121: C: Layout/LineLength: Line is too long. [146/120] (https://rubystyle.guide#max-line-length) '%{application_name} has been shared with you'), application_name: ApplicationService.application_name)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ app/models/user.rb:412:3: C: Metrics/AbcSize: Assignment Branch Condition size for archive is too high. [<10, 15, 0> 18.03/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def archive ... ^^^^^^^^^^^ app/models/user.rb:429:3: C: Metrics/AbcSize: Assignment Branch Condition size for merge is too high. [<1, 17, 0> 17.03/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def merge(to_be_merged) ... ^^^^^^^^^^^^^^^^^^^^^^^ app/models/user/at_csv.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class User::AtCsv. class AtCsv ^^^^^^^^^^^ app/models/user/at_csv.rb:12:5: C: Metrics/AbcSize: Assignment Branch Condition size for to_csv is too high. [<10, 20, 8> 23.75/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def to_csv ... ^^^^^^^^^^ app/models/user/at_csv.rb:12:5: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for to_csv is too high. [8/7] def to_csv ... ^^^^^^^^^^ app/models/user/at_csv.rb:12:5: C: Metrics/MethodLength: Method has too many lines. [21/20] (https://rubystyle.guide#short-methods) def to_csv ... ^^^^^^^^^^ app/models/user/at_csv.rb:12:5: C: Metrics/PerceivedComplexity: Perceived complexity for to_csv is too high. [9/8] def to_csv ... ^^^^^^^^^^ app/services/api/v1/auth/jwt/authorization_service.rb:7:9: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::Auth::Jwt::AuthorizationService. class AuthorizationService ^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/auth/jwt/authorization_service.rb:22:11: C: Metrics/AbcSize: Assignment Branch Condition size for client is too high. [<5, 19, 7> 20.86/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def client ... ^^^^^^^^^^ app/services/api/v1/auth/jwt/authorization_service.rb:22:11: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for client is too high. [8/7] def client ... ^^^^^^^^^^ app/services/api/v1/auth/jwt/json_web_token.rb:7:9: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::Auth::Jwt::JsonWebToken. class JsonWebToken ^^^^^^^^^^^^^^^^^^ app/services/api/v1/contextual_error_service.rb:33:9: C: Metrics/AbcSize: Assignment Branch Condition size for contextualize is too high. [<3, 17, 5> 17.97/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def contextualize(errors:, context: 'DMP') ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/conversion_service.rb:5:5: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::ConversionService. class ConversionService ^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization/contributor.rb:6:7: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::Deserialization::Contributor. class Contributor ^^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization/dataset.rb:6:7: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::Deserialization::Dataset. class Dataset ^^^^^^^^^^^^^ app/services/api/v1/deserialization/funding.rb:6:7: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::Deserialization::Funding. class Funding ^^^^^^^^^^^^^ app/services/api/v1/deserialization/identifier.rb:6:7: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::Deserialization::Identifier. class Identifier ^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization/org.rb:6:7: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::Deserialization::Org. class Org ^^^^^^^^^ app/services/api/v1/deserialization/org.rb:17:11: C: Metrics/AbcSize: Assignment Branch Condition size for deserialize is too high. [<6, 17, 5> 18.71/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def deserialize(json: {}) ... ^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization/plan.rb:6:7: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::Deserialization::Plan. class Plan ^^^^^^^^^^ app/services/api/v1/deserialization/plan.rb:46:11: C: Metrics/AbcSize: Assignment Branch Condition size for deserialize is too high. [<11, 22, 4> 24.92/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def deserialize(json: {}) ... ^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization/plan.rb:113:11: C: Metrics/AbcSize: Assignment Branch Condition size for deserialize_project is too high. [<4, 19, 5> 20.05/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def deserialize_project(plan:, json: {}) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization_service.rb:5:5: C: Style/Documentation: Missing top-level documentation comment for class Api::V1::DeserializationService. class DeserializationService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization_service.rb:23:9: C: Metrics/AbcSize: Assignment Branch Condition size for attach_identifier is too high. [<2, 20, 10> 22.45/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def attach_identifier(object:, json:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization_service.rb:23:9: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for attach_identifier is too high. [10/7] def attach_identifier(object:, json:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization_service.rb:23:9: C: Metrics/PerceivedComplexity: Perceived complexity for attach_identifier is too high. [10/8] def attach_identifier(object:, json:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/deserialization_service.rb:57:9: C: Metrics/AbcSize: Assignment Branch Condition size for app_extensions is too high. [<3, 17, 4> 17.72/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def app_extensions(json: {}) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/json_validation_service.rb:50:9: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for validation_errors is too high. [8/7] def validation_errors(json:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/persistence_service.rb:8:9: C: Metrics/AbcSize: Assignment Branch Condition size for safe_save is too high. [<7, 24, 4> 25.32/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def safe_save(plan:) ... ^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/persistence_service.rb:66:9: C: Metrics/AbcSize: Assignment Branch Condition size for safe_save_contributor is too high. [<3, 20, 5> 20.83/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def safe_save_contributor(contributor:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/api/v1/persistence_service.rb:87:9: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for deduplicate_contributors is too high. [8/7] def deduplicate_contributors(contributors:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/application_service.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class ApplicationService. class ApplicationService ^^^^^^^^^^^^^^^^^^^^^^^^ app/services/external_apis/base_service.rb:8:3: C: Style/Documentation: Missing top-level documentation comment for class ExternalApis::BaseService. class BaseService ^^^^^^^^^^^^^^^^^ app/services/external_apis/ror_service.rb:108:7: C: Metrics/AbcSize: Assignment Branch Condition size for process_pages is too high. [<8, 15, 9> 19.24/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def process_pages(term:, json:, filters: []) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/external_apis/ror_service.rb:108:7: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for process_pages is too high. [8/7] def process_pages(term:, json:, filters: []) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/external_apis/ror_service.rb:133:7: C: Metrics/AbcSize: Assignment Branch Condition size for parse_results is too high. [<2, 21, 5> 21.68/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def parse_results(json:) ... ^^^^^^^^^^^^^^^^^^^^^^^^ app/services/locale_service.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class LocaleService. class LocaleService ^^^^^^^^^^^^^^^^^^^ app/services/org/create_created_plan_service.rb:15:3: C: Style/Documentation: Missing top-level documentation comment for class Org::CreateCreatedPlanService. class CreateCreatedPlanService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/create_exported_plan_service.rb:14:3: C: Style/Documentation: Missing top-level documentation comment for class Org::CreateExportedPlanService. class CreateExportedPlanService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/create_joined_user_service.rb:11:3: C: Style/Documentation: Missing top-level documentation comment for class Org::CreateJoinedUserService. class CreateJoinedUserService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/create_last_month_created_plan_service.rb:15:3: C: Style/Documentation: Missing top-level documentation comment for class Org::CreateLastMonthCreatedPlanService. class CreateLastMonthCreatedPlanService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/create_last_month_exported_plan_service.rb:14:3: C: Style/Documentation: Missing top-level documentation comment for class Org::CreateLastMonthExportedPlanService. class CreateLastMonthExportedPlanService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/create_last_month_joined_user_service.rb:11:3: C: Style/Documentation: Missing top-level documentation comment for class Org::CreateLastMonthJoinedUserService. class CreateLastMonthJoinedUserService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/create_last_month_shared_plan_service.rb:13:3: C: Style/Documentation: Missing top-level documentation comment for class Org::CreateLastMonthSharedPlanService. class CreateLastMonthSharedPlanService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/create_shared_plan_service.rb:13:3: C: Style/Documentation: Missing top-level documentation comment for class Org::CreateSharedPlanService. class CreateSharedPlanService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/monthly_usage_service.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class Org::MonthlyUsageService. class MonthlyUsageService ^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/total_count_created_plan_service.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class Org::TotalCountCreatedPlanService. class TotalCountCreatedPlanService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/total_count_joined_user_service.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class Org::TotalCountJoinedUserService. class TotalCountJoinedUserService ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org/total_count_stat_service.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class Org::TotalCountStatService. class TotalCountStatService ^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org_selection/hash_to_org_service.rb:43:7: C: Metrics/AbcSize: Assignment Branch Condition size for to_identifiers is too high. [<9, 15, 6> 18.49/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def to_identifiers(hash:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/org_selection/hash_to_org_service.rb:114:9: C: [Correctable] Style/RedundantArgument: Argument ' ' is redundant because it is implied by default. OrgSelection::SearchService.name_without_alias(name: hash[:name]) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/services/template/upgrade_customization_service.rb:62:5: C: Metrics/MethodLength: Method has too many lines. [21/20] (https://rubystyle.guide#short-methods) def call ... ^^^^^^^^ app/validators/after_validator.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class AfterValidator. class AfterValidator < ActiveModel::EachValidator ^^^^^^^^^^^^^^^^^^^^ app/validators/after_validator.rb:4:38: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). DEFAULT_MESSAGE = _('must be after %{date}') ^^^^^^^ app/validators/after_validator.rb:6:3: C: Metrics/AbcSize: Assignment Branch Condition size for validate_each is too high. [<1, 19, 9> 21.05/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def validate_each(record, attribute, value) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/validators/answer_for_correct_template_validator.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class AnswerForCorrectTemplateValidator. class AnswerForCorrectTemplateValidator < ActiveModel::Validator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/validators/email_validator.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class EmailValidator. class EmailValidator < ActiveModel::EachValidator ^^^^^^^^^^^^^^^^^^^^ app/validators/org_links_validator.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class OrgLinksValidator. class OrgLinksValidator < ActiveModel::Validator ^^^^^^^^^^^^^^^^^^^^^^^ app/validators/template_links_validator.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class TemplateLinksValidator. class TemplateLinksValidator < ActiveModel::Validator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ app/validators/template_links_validator.rb:5:3: C: Metrics/AbcSize: Assignment Branch Condition size for validate is too high. [<4, 20, 6> 21.26/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def validate(record) ... ^^^^^^^^^^^^^^^^^^^^ app/validators/template_links_validator.rb:12:30: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). msg = _('The key %{key} does not have a valid set of object links') ^^^^^^ app/validators/template_links_validator.rb:16:53: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). record.errors[:links] << (format(_('A key %{key} is expected for links hash'), key: k)) ^^^^^^ app/validators/url_validator.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class UrlValidator. class UrlValidator < ActiveModel::EachValidator ^^^^^^^^^^^^^^^^^^ config.ru:4:26: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) require File.expand_path(File.dirname(__FILE__) + '/config/environment') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ config/application.rb:14:3: C: Style/Documentation: Missing top-level documentation comment for class DMPRoadmap::Application. class Application < Rails::Application ^^^^^^^^^^^^^^^^^ config/environments/production.rb:89:50: C: [Correctable] Style/GlobalStdStream: Use $stdout instead of STDOUT. (https://rubystyle.guide#global-stdout) logger = ActiveSupport::Logger.new(STDOUT) ^^^^^^ config/initializers/_dmproadmap.rb:18:3: C: Style/Documentation: Missing top-level documentation comment for class DMPRoadmap::Application. class Application < Rails::Application ^^^^^^^^^^^^^^^^^ config/initializers/_dmproadmap.rb:41:7: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) line_1: 'Princess Elisabeth Station', ^^^^^^ config/initializers/_dmproadmap.rb:42:7: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) line_2: '123 Freezing Cold Street', ^^^^^^ config/initializers/_dmproadmap.rb:43:7: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) line_3: 'Suite 123', ^^^^^^ config/initializers/_dmproadmap.rb:44:7: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) line_4: 'Polar Vortex, ABC-345', ^^^^^^ config/initializers/dmproadmap_schema_dumper.rb:12:5: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for table is too high. [11/7] def table(table, stream) ... ^^^^^^^^^^^^^^^^^^^^^^^^ config/initializers/dmproadmap_schema_dumper.rb:12:5: C: Metrics/PerceivedComplexity: Perceived complexity for table is too high. [10/8] def table(table, stream) ... ^^^^^^^^^^^^^^^^^^^^^^^^ config/initializers/htmlto_word_xslt_helper.rb:9:3: C: Style/Documentation: Missing top-level documentation comment for module Htmltoword::XSLTHelper. module XSLTHelper ^^^^^^^^^^^^^^^^^ config/initializers/jbuilder_prettify.rb:6:1: C: Style/Documentation: Missing top-level documentation comment for class Jbuilder. class Jbuilder ^^^^^^^^^^^^^^ config/puma.rb:9:21: C: [Correctable] Style/RedundantFetchBlock: Use fetch('RAILS_MAX_THREADS', 5) instead of fetch('RAILS_MAX_THREADS') { 5 }. (https://github.com/JuanitoFatas/fast-ruby#hashfetch-with-argument-vs-hashfetch--block-code) threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ config/puma.rb:14:17: C: [Correctable] Style/RedundantFetchBlock: Use fetch('PORT', 3000) instead of fetch('PORT') { 3000 }. (https://github.com/JuanitoFatas/fast-ruby#hashfetch-with-argument-vs-hashfetch--block-code) port ENV.fetch('PORT') { 3000 } ^^^^^^^^^^^^^^^^^^^^^^ config/puma.rb:18:17: C: [Correctable] Style/RedundantFetchBlock: Use fetch('RAILS_ENV', 'development') instead of fetch('RAILS_ENV') { 'development' }. (https://github.com/JuanitoFatas/fast-ruby#hashfetch-with-argument-vs-hashfetch--block-code) environment ENV.fetch('RAILS_ENV') { 'development' } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ config/puma.rb:26:13: C: [Correctable] Style/RedundantFetchBlock: Use fetch('WEB_CONCURRENCY', 2) instead of fetch('WEB_CONCURRENCY') { 2 }. (https://github.com/JuanitoFatas/fast-ruby#hashfetch-with-argument-vs-hashfetch--block-code) workers ENV.fetch('WEB_CONCURRENCY') { 2 } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ config/routes.rb:274:7: W: Lint/EmptyBlock: Empty block detected. resources :conditions, only: %i[new show] do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ config/routes.rb:316:11: W: Lint/EmptyBlock: Empty block detected. resources :questions, only: %i[show edit new update create destroy] do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/cleanup/deprecators/get_deprecator.rb:14:18: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). MESSAGE = '%{deprecated_method}s is deprecated. '\ ^^^^^^^^^^^^^^^^^^^^ lib/cleanup/deprecators/get_deprecator.rb:15:43: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). 'Instead, you should use: %{new_method}s. '\ ^^^^^^^^^^^^^ lib/cleanup/deprecators/predicate_deprecator.rb:13:18: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). MESSAGE = '%{deprecated_method}s is deprecated. '\ ^^^^^^^^^^^^^^^^^^^^ lib/cleanup/deprecators/predicate_deprecator.rb:14:43: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). 'Instead, you should use: %{new_method}s. '\ ^^^^^^^^^^^^^ lib/cleanup/deprecators/set_deprecator.rb:14:18: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). MESSAGE = '%{deprecated_method}s is deprecated. '\ ^^^^^^^^^^^^^^^^^^^^ lib/cleanup/deprecators/set_deprecator.rb:15:43: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). 'Instead, you should use: %{new_method}s. '\ ^^^^^^^^^^^^^ lib/csvable.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module Csvable. module Csvable ^^^^^^^^^^^^^^ lib/csvable.rb:6:5: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for from_array_of_hashes is too high. [8/7] def from_array_of_hashes(data = [], humanize = true, sep = ',') ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/csvable.rb:6:5: C: Metrics/PerceivedComplexity: Perceived complexity for from_array_of_hashes is too high. [9/8] def from_array_of_hashes(data = [], humanize = true, sep = ',') ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/csvable.rb:6:41: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use humanize: true instead of humanize = true. (https://rubystyle.guide#boolean-keyword-arguments) def from_array_of_hashes(data = [], humanize = true, sep = ',') ^^^^^^^^^^^^^^^ lib/custom_failure.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for class CustomFailure. class CustomFailure < Devise::FailureApp ^^^^^^^^^^^^^^^^^^^ lib/data_cleanup.rb:8:1: C: Style/Documentation: Missing top-level documentation comment for module DataCleanup. module DataCleanup ^^^^^^^^^^^^^^^^^^ lib/data_cleanup/instance_check.rb:8:5: C: Metrics/AbcSize: Assignment Branch Condition size for call is too high. [<2, 23, 3> 23.28/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def call(instance) ... ^^^^^^^^^^^^^^^^^^ lib/data_cleanup/model_check.rb:14:5: C: Metrics/AbcSize: Assignment Branch Condition size for call is too high. [<5, 23, 7> 24.56/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def call ... ^^^^^^^^ lib/data_cleanup/rules.rb:6:3: C: Style/Documentation: Missing top-level documentation comment for module DataCleanup::Rules. module Rules ^^^^^^^^^^^^ lib/faker/language.rb:4:3: C: Style/Documentation: Missing top-level documentation comment for class Faker::Language. class Language < Base ^^^^^^^^^^^^^^ lib/generators/data_cleanup_rule/data_cleanup_rule_generator.rb:45:13: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). format('%{rule_name}s on %{model_name}s', rule_name: rule_class_name.underscore ^^^^^^^^^^^^ lib/generators/data_cleanup_rule/data_cleanup_rule_generator.rb:45:30: C: Style/FormatStringToken: Prefer annotated tokens (like %s) over template tokens (like %{foo}). format('%{rule_name}s on %{model_name}s', rule_name: rule_class_name.underscore ^^^^^^^^^^^^^ lib/global_helpers.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module GlobalHelpers. module GlobalHelpers ^^^^^^^^^^^^^^^^^^^^ lib/org_date_rangeable.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module OrgDateRangeable. module OrgDateRangeable ^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/auto_annotate_models.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. # NOTE: only doing this in development as some production environments (Heroku) ^ lib/tasks/auto_annotate_models.rake:6:3: C: Metrics/BlockLength: Block has too many lines. [42/25] task :set_annotation_options do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. require 'data_cleanup' ^ lib/tasks/data_cleanup.rake:3:1: C: Metrics/BlockLength: Block has too many lines. [217/25] namespace :data_cleanup do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:39:3: C: Metrics/BlockLength: Block has too many lines. [39/25] task find_known_invalidations: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:40:5: C: Metrics/BlockLength: Block has too many lines. [37/25] models.each do |model| ... ^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:44:7: C: Metrics/BlockLength: Block has too many lines. [33/25] model._validate_callbacks.to_a.collect(&:filter).each do |filter| ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:106:19: C: [Correctable] Style/SymbolProc: Pass &:deactivate! as an argument to each instead of a block. Plan.all.each { |plan| plan.deactivate! } ^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:133:3: C: Metrics/AbcSize: Assignment Branch Condition size for check_presence is too high. [<11, 35, 14> 39.27/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def check_presence(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:133:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for check_presence is too high. [12/7] def check_presence(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:133:3: C: Metrics/MethodLength: Method has too many lines. [25/20] (https://rubystyle.guide#short-methods) def check_presence(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:133:3: C: Metrics/PerceivedComplexity: Perceived complexity for check_presence is too high. [14/8] def check_presence(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:172:3: C: Metrics/AbcSize: Assignment Branch Condition size for check_uniqueness is too high. [<6, 18, 5> 19.62/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def check_uniqueness(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:182:3: C: Metrics/AbcSize: Assignment Branch Condition size for check_inclusion is too high. [<5, 18, 2> 18.79/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def check_inclusion(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:190:121: C: Layout/LineLength: Line is too long. [126/120] (https://rubystyle.guide#max-line-length) msg = " #{ids.count} records that do not have a valid value for #{filter.attributes}, should be #{filter.options[:in]}" ^^^^^^ lib/tasks/data_cleanup.rake:195:3: C: Metrics/AbcSize: Assignment Branch Condition size for check_format is too high. [<6, 19, 9> 21.86/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def check_format(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:204:18: W: Lint/UselessAssignment: Useless assignment to variable - msg. Use _ or _msg as a variable name to indicate that it won't be used. (https://rubystyle.guide#underscore-unused-vars) ids, msg = check_local_validators(klass, [attr], EmailValidator) ^^^ lib/tasks/data_cleanup.rake:215:3: C: Metrics/AbcSize: Assignment Branch Condition size for check_length is too high. [<11, 26, 6> 28.86/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def check_length(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:215:3: C: Metrics/MethodLength: Method has too many lines. [21/20] (https://rubystyle.guide#short-methods) def check_length(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:230:11: W: Lint/UselessAssignment: Useless assignment to variable - should. (https://rubystyle.guide#underscore-unused-vars) should += ' and ' ^^^^^^ lib/tasks/data_cleanup.rake:242:3: C: Metrics/AbcSize: Assignment Branch Condition size for check_numericality is too high. [<14, 27, 8> 31.45/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def check_numericality(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:242:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for check_numericality is too high. [9/7] def check_numericality(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:242:3: C: Metrics/MethodLength: Method has too many lines. [22/20] (https://rubystyle.guide#short-methods) def check_numericality(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:242:3: C: Metrics/PerceivedComplexity: Perceived complexity for check_numericality is too high. [9/8] def check_numericality(klass, filter) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/data_cleanup.rake:264:7: W: Lint/Void: Literal [ids, " #{ids.count} records that are an invalid #{filter.attributes} because it should #{shoulda}"] used in void context. [ids, " #{ids.count} records that are an invalid #{filter.attributes} because it should #{shoulda}"] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/doc.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. namespace :tomdoc do ^ lib/tasks/doc.rake:34:1: W: Lint/EmptyBlock: Empty block detected. task tomdoc: ['tomdoc:clear', 'tomdoc:app', 'tomdoc:open'] do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/factory_bot.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. namespace :factory_bot do ^ lib/tasks/factory_bot.rake:10:12: C: [Correctable] Style/SpecialGlobalVars: Prefer $CHILD_STATUS from the stdlib 'English' module (don't forget to require it) over $?. (https://rubystyle.guide#no-cryptic-perlisms) exit $?.exitstatus ^^ lib/tasks/gettext.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. namespace :gettext do ^ lib/tasks/initialize_data.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. namespace :initialize_data do ^ lib/tasks/migrate.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. # These Tasks are for the early migrations of the codebase ^ lib/tasks/migrate.rake:3:1: C: Metrics/BlockLength: Block has too many lines. [304/25] namespace :migrate do ... ^^^^^^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:5:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task prep_for_1_0: :environment do ^^^^^^^^^^^^ lib/tasks/migrate.rake:11:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task to_04: :environment do ^^^^^ lib/tasks/migrate.rake:45:3: C: Metrics/BlockLength: Block has too many lines. [119/25] task seed: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:76:7: W: Lint/ShadowedArgument: Argument role was shadowed by a local variable before it was used. role = Role.new ^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:181:3: C: Metrics/BlockLength: Block has too many lines. [47/25] task fix_languages: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:286:8: C: [Correctable] Style/NumericPredicate: Use users.length.positive? instead of users.length > 0. (https://rubystyle.guide#predicate-methods) if users.length > 0 ^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:286:8: C: [Correctable] Style/ZeroLengthPredicate: Use !empty? instead of length > 0. if users.length > 0 ^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:302:48: C: [Correctable] Style/SymbolProc: Pass &:identifier_scheme_id as an argument to collect instead of a block. schemes = u.user_identifiers.collect { |i| i.identifier_scheme_id } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:319:10: C: [Correctable] Style/NumericPredicate: Use users.length.positive? instead of users.length > 0. (https://rubystyle.guide#predicate-methods) if users.length > 0 ^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:319:10: C: [Correctable] Style/ZeroLengthPredicate: Use !empty? instead of length > 0. if users.length > 0 ^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:331:50: C: [Correctable] Style/SymbolProc: Pass &:identifier_scheme_id as an argument to collect instead of a block. schemes = u.user_identifiers.collect { |i| i.identifier_scheme_id } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:333:13: C: Metrics/BlockNesting: Avoid more than 3 levels of block nesting. (https://rubystyle.guide#three-is-the-number-thou-shalt-count) next if schemes.include?(scheme.id) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/migrate.rake:345:121: C: Layout/LineLength: Line is too long. [133/120] (https://rubystyle.guide#max-line-length) questions = Question.joins(:annotations).group('questions.id').having('count(annotations.id) > count(DISTINCT annotations.text)') ^^^^^^^^^^^^^ lib/tasks/migrate.rake:352:24: C: [Correctable] Style/SymbolProc: Pass &:destroy as an argument to each instead of a block. conflicts.each { |c| c.destroy } ^^^^^^^^^^^^^^^^^ lib/tasks/stat.rake:1:1: C: Metrics/BlockLength: Block has too many lines. [80/25] namespace :stat do ... ^^^^^^^^^^^^^^^^^^ lib/tasks/stat.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. namespace :stat do ^ lib/tasks/stat.rake:26:7: W: Lint/Void: Variable task used in void context. task ^^^^ lib/tasks/stat.rake:49:7: W: Lint/Void: Variable task used in void context. task ^^^^ lib/tasks/upgrade.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. # Upgrade tasks for versions < 3.0. See https://github.com/DMPRoadmap/roadmap/releases for information ^ lib/tasks/upgrade.rake:5:1: C: Metrics/BlockLength: Block has too many lines. [1106/25] namespace :upgrade do ... ^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:7:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v2_3_0: :environment do ^^^^^^ lib/tasks/upgrade.rake:33:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v2_1_6: :environment do ^^^^^^ lib/tasks/upgrade.rake:38:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v2_1_3: :environment do ^^^^^^ lib/tasks/upgrade.rake:46:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v2_1_2: :environment do ^^^^^^ lib/tasks/upgrade.rake:51:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v2_1_0: :environment do ^^^^^^ lib/tasks/upgrade.rake:56:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v2_0_0_part_1: :environment do ^^^^^^^^^^^^^ lib/tasks/upgrade.rake:64:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v2_0_0_part_2: :environment do ^^^^^^^^^^^^^ lib/tasks/upgrade.rake:72:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v1_1_2: :environment do ^^^^^^ lib/tasks/upgrade.rake:80:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v1_0_0: :environment do ^^^^^^ lib/tasks/upgrade.rake:89:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task v0_3_3: :environment do ^^^^^^ lib/tasks/upgrade.rake:177:121: C: Layout/LineLength: Line is too long. [122/120] (https://rubystyle.guide#max-line-length) # Generate the tokens directly instead of via the User.keep_or_generate_token! method so that we do not spam users!! ^^ lib/tasks/upgrade.rake:187:3: C: Metrics/BlockLength: Block has too many lines. [55/25] task remove_duplicate_answers: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:189:5: C: Metrics/BlockLength: Block has too many lines. [53/25] ActiveRecord::Base.transaction do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:190:121: C: Layout/LineLength: Line is too long. [226/120] (https://rubystyle.guide#max-line-length) plan_ids = ActiveRecord::Base.connection.select_all('SELECT a1.plan_id as plan_id FROM Answers a1 INNER JOIN Answers a2 ON a1.plan_id = a2.plan_id AND a1.question_id = a2.question_id WHERE a1.id > a2.id').to_a.map do |h| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:194:7: C: Metrics/BlockLength: Block has too many lines. [47/25] plans.each do |plan| ... ^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:195:9: C: Metrics/BlockLength: Block has too many lines. [45/25] plan.answers.pluck(:question_id).uniq.each do |question_id| ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:199:105: C: [Correctable] Style/SymbolProc: Pass &:id as an argument to map instead of a block. puts "found duplicate for plan:#{plan.id}\tquestion:#{question_id} \n\tanswers:[#{answers.map do |answer| ... ^^^^^^^^^^^ lib/tasks/upgrade.rake:217:16: C: [Correctable] Style/NumericPredicate: Use num_text.zero? instead of num_text == 0. (https://rubystyle.guide#predicate-methods) if num_text == 0 && answer.text.present? # case first present text ^^^^^^^^^^^^^ lib/tasks/upgrade.rake:224:33: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) new_answer.text = text + '

-------------

' + answer.text ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:249:10: W: Lint/AssignmentInCondition: Use == if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. (https://rubystyle.guide#safe-assignment-in-condition) if t = Theme.find_by(title: 'Project Description') then t.destroy end ^ lib/tasks/upgrade.rake:250:10: W: Lint/AssignmentInCondition: Use == if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. (https://rubystyle.guide#safe-assignment-in-condition) if t = Theme.find_by(title: 'Project Name') then t.destroy end ^ lib/tasks/upgrade.rake:251:10: W: Lint/AssignmentInCondition: Use == if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. (https://rubystyle.guide#safe-assignment-in-condition) if t = Theme.find_by(title: 'ID') then t.destroy end ^ lib/tasks/upgrade.rake:252:10: W: Lint/AssignmentInCondition: Use == if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. (https://rubystyle.guide#safe-assignment-in-condition) if t = Theme.find_by(title: 'PI / Researcher') then t.destroy end ^ lib/tasks/upgrade.rake:266:3: C: Metrics/BlockLength: Block has too many lines. [42/25] task theme_transform: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:267:5: C: Metrics/BlockLength: Block has too many lines. [40/25] ActiveRecord::Base.transaction do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:321:22: W: Lint/AssignmentInCondition: Use == if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. (https://rubystyle.guide#safe-assignment-in-condition) if deltheme = Theme.find_by(title: t) then deltheme.destroy end ^ lib/tasks/upgrade.rake:330:9: W: Lint/UselessAssignment: Useless assignment to variable - themelist. (https://rubystyle.guide#underscore-unused-vars) themelist = [] ^^^^^^^^^ lib/tasks/upgrade.rake:354:42: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) themeguidances.first.text += '

——

' + guidance.text ^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:356:15: C: [Correctable] Style/CommentedKeyword: Do not place comments on the same line as the end keyword. end # themeguidances loop ^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:358:13: C: [Correctable] Style/CommentedKeyword: Do not place comments on the same line as the end keyword. end # allthemes loop ^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:359:11: C: [Correctable] Style/CommentedKeyword: Do not place comments on the same line as the end keyword. end # GuidanceGroup loop ^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:364:3: C: Metrics/BlockLength: Block has too many lines. [39/25] task remove_duplicated_non_customised_template_versions: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:388:10: C: [Correctable] Style/NumericPredicate: Use num_plans.positive? instead of num_plans > 0. (https://rubystyle.guide#predicate-methods) if num_plans > 0 ^^^^^^^^^^^^^ lib/tasks/upgrade.rake:395:121: C: Layout/LineLength: Line is too long. [125/120] (https://rubystyle.guide#max-line-length) puts "template with id: #{template.id} has been ARCHIVED since it had plans associated but no customised templates" ^^^^^ lib/tasks/upgrade.rake:407:3: C: Metrics/BlockLength: Block has too many lines. [39/25] task remove_duplicated_customised_template_versions: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:434:10: C: [Correctable] Style/NumericPredicate: Use num_plans.positive? instead of num_plans > 0. (https://rubystyle.guide#predicate-methods) if num_plans > 0 ^^^^^^^^^^^^^ lib/tasks/upgrade.rake:454:121: C: Layout/LineLength: Line is too long. [122/120] (https://rubystyle.guide#max-line-length) desc 'Org.contact_email is now required, sets any nil values to the helpdesk email defined in dmproadmap.rb initializer' ^^ lib/tasks/upgrade.rake:503:3: C: Metrics/BlockLength: Block has too many lines. [26/25] task add_other_org: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:537:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task add_default_values_v2_0_0: :environment do ^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:556:3: C: Metrics/BlockLength: Block has too many lines. [70/25] task add_versioning_id_to_templates: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:572:5: C: Metrics/BlockLength: Block has too many lines. [44/25] Template.latest_version.where(customization_of: nil) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:579:7: C: Metrics/BlockLength: Block has too many lines. [40/25] funder_template.phases.each do |funder_phase| ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:589:9: C: Metrics/BlockLength: Block has too many lines. [31/25] funder_phase.sections.each do |funder_section| ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:712:3: C: Metrics/BlockLength: Block has too many lines. [26/25] task add_versionable_id_to_question_options: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:819:3: C: Metrics/BlockLength: Block has too many lines. [28/25] task convert_user_identifiers: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:856:3: C: Metrics/BlockLength: Block has too many lines. [30/25] task convert_org_identifiers: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:884:121: C: Layout/LineLength: Line is too long. [124/120] (https://rubystyle.guide#max-line-length) p "#{identifiers.length - count} records could not be transferred. Run the following query manually to identify them:" ^^^^ lib/tasks/upgrade.rake:887:121: C: Layout/LineLength: Line is too long. [121/120] (https://rubystyle.guide#max-line-length) p " WHERE identifiers.identifier_scheme_id = org_identifiers.identifier_scheme_id AND identifiable_type = 'Org'" ^ lib/tasks/upgrade.rake:899:3: C: Metrics/BlockLength: Block has too many lines. [48/25] task retrieve_ror_fundref_ids: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:903:11: C: Metrics/BlockLength: Block has too many lines. [39/25] out = CSV.generate do |csv| ... ^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:908:121: C: Layout/LineLength: Line is too long. [133/120] (https://rubystyle.guide#max-line-length) p 'The results will be written to tmp/ror_fundref_ids.csv to facilitate review and any corrections that may need to be made.' ^^^^^^^^^^^^^ lib/tasks/upgrade.rake:909:121: C: Layout/LineLength: Line is too long. [163/120] (https://rubystyle.guide#max-line-length) p 'The CSV file contains the Org name stored in your DB next to the ROR org name that was matched. Use these 2 values to determine if the match was valid.' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:926:34: W: Lint/ShadowingOuterLocalVariable: Shadowing outer local variable - rslt. rslt = rslts.select { |rslt| rslt[:weight] <= 1 }.first ^^^^ lib/tasks/upgrade.rake:952:121: C: Layout/LineLength: Line is too long. [134/120] (https://rubystyle.guide#max-line-length) p 'ROR appears to be offline or your configuration is invalid. Heartbeat check failed. Refer to the log for more information.' ^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:964:3: C: Metrics/BlockLength: Block has too many lines. [45/25] task migrate_other_organisation_to_org: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:977:5: C: Metrics/BlockLength: Block has too many lines. [33/25] users.each do |user| ... ^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1008:45: C: [Correctable] Style/NumericPredicate: Use (result[:weight]).zero? instead of result[:weight] == 0. (https://rubystyle.guide#predicate-methods) matches = matches.select { |result| result[:weight] == 0 } ^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1016:18: C: [Correctable] Style/RedundantArgument: Argument ' ' is redundant because it is implied by default. abbrev = OrgSelection::SearchService.name_without_alias(name: name) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1035:3: C: Metrics/BlockLength: Block has too many lines. [45/25] task migrate_contributors: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1042:5: C: Metrics/BlockLength: Block has too many lines. [41/25] Parallel.map(plans, in_threads: 8) do |plan| ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1093:10: C: [Correctable] Style/NumericPredicate: Use plan.contributors.length.positive? instead of plan.contributors.length > 0. (https://rubystyle.guide#predicate-methods) if plan.contributors.length > 0 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1093:10: C: [Correctable] Style/ZeroLengthPredicate: Use !empty? instead of length > 0. if plan.contributors.length > 0 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1100:3: C: Metrics/BlockLength: Block has too many lines. [34/25] task migrate_plan_org_and_funder: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1171:3: C: Metrics/BlockLength: Block has too many lines. [30/25] task results_2_2_0_part1: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1190:121: C: Layout/LineLength: Line is too long. [124/120] (https://rubystyle.guide#max-line-length) p ' NOTE: org_identifier and user_identifiers tables are being deprecated and will be dropped in a future release.' ^^^^ lib/tasks/upgrade.rake:1200:121: C: Layout/LineLength: Line is too long. [215/120] (https://rubystyle.guide#max-line-length) p " insert into identifiers (identifiable_type, identifier_scheme_id, attrs, identifiable_id, value) values ('Org', [identifier_scheme_id], '{}', [orgs.id], 'https://doi.org/10.13039/0000000000');" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1201:121: C: Layout/LineLength: Line is too long. [197/120] (https://rubystyle.guide#max-line-length) p " update identifiers set `value` = 'https://ror.org/123456789' where identifiable_id = [orgs.id] and identifier_scheme_id = [identifier_scheme_id] and identifiable_type= 'Org';" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1206:3: C: Metrics/BlockLength: Block has too many lines. [34/25] task results_2_2_0_part2: :environment do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1207:5: W: Lint/UselessAssignment: Useless assignment to variable - ror. (https://rubystyle.guide#underscore-unused-vars) ror = IdentifierScheme.find_by(name: 'ror') ^^^ lib/tasks/upgrade.rake:1208:5: W: Lint/UselessAssignment: Useless assignment to variable - fundref. (https://rubystyle.guide#underscore-unused-vars) fundref = IdentifierScheme.find_by(name: 'fundref') ^^^^^^^ lib/tasks/upgrade.rake:1224:121: C: Layout/LineLength: Line is too long. [129/120] (https://rubystyle.guide#max-line-length) p ' `SELECT id, email, other_organisation FROM users WHERE org_id = (SELECT orgs.id FROM orgs WHERE is_other = true);' ^^^^^^^^^ lib/tasks/upgrade.rake:1232:121: C: Layout/LineLength: Line is too long. [145/120] (https://rubystyle.guide#max-line-length) p " Added #{number_with_delimiter(contributors_converted)} Contributor based on the old DataContact, PrincipalInvestigator and Plan Owner" ^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1233:121: C: Layout/LineLength: Line is too long. [149/120] (https://rubystyle.guide#max-line-length) p ' NOTE: the old data_contact and principal_investigator fields on the plans table are deprecated and will be removed in a future release.' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1236:121: C: Layout/LineLength: Line is too long. [172/120] (https://rubystyle.guide#max-line-length) p " Attached #{number_with_delimiter(funders_converted)} Plans to a Funder based on either the Template's Org (if it was a funder) or the name in funder_name field." ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1238:121: C: Layout/LineLength: Line is too long. [129/120] (https://rubystyle.guide#max-line-length) p ' NOTE: funder_name and grant_number fields on the plans table are deprecated and will be dropped in a future release' ^^^^^^^^^ lib/tasks/upgrade.rake:1248:121: C: Layout/LineLength: Line is too long. [122/120] (https://rubystyle.guide#max-line-length) Org.where(feedback_email_subject: nil).update_all(feedback_email_subject: Org.feedback_confirmation_default_subject) ^^ lib/tasks/upgrade.rake:1272:3: C: Metrics/AbcSize: Assignment Branch Condition size for to_contributor is too high. [<15, 31, 12> 36.47/17] (http://c2.com/cgi/wiki?AbcMetric, https://en.wikipedia.org/wiki/ABC_Software_Metric) def to_contributor(plan, name, email, phone, identifier, org) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1272:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for to_contributor is too high. [12/7] def to_contributor(plan, name, email, phone, identifier, org) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1272:3: C: Metrics/MethodLength: Method has too many lines. [26/20] (https://rubystyle.guide#short-methods) def to_contributor(plan, name, email, phone, identifier, org) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1272:3: C: Metrics/PerceivedComplexity: Perceived complexity for to_contributor is too high. [12/8] def to_contributor(plan, name, email, phone, identifier, org) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/upgrade.rake:1272:21: C: Metrics/ParameterLists: Avoid parameter lists longer than 5 parameters. [6/5] (https://rubystyle.guide#too-many-params) def to_contributor(plan, name, email, phone, identifier, org) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/utils/templates.rake:232:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for find_related_versionable_id is too high. [9/7] def find_related_versionable_id(original_template:, record:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/utils/templates.rake:232:3: C: Metrics/PerceivedComplexity: Perceived complexity for find_related_versionable_id is too high. [9/8] def find_related_versionable_id(original_template:, record:) ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lib/tasks/v3.rake:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. # Upgrade tasks for 3.x versions. See https://github.com/DMPRoadmap/roadmap/releases for information ^ lib/tasks/v3.rake:4:1: C: Metrics/BlockLength: Block has too many lines. [49/25] namespace :v3 do ... ^^^^^^^^^^^^^^^^ lib/tasks/v3.rake:6:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task upgrade_3_0_0: :environment do ^^^^^^^^^^^^^ lib/tasks/v3.rake:13:8: C: Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers) task upgrade_3_1_0: :environment do ^^^^^^^^^^^^^ lib/unique_random.rb:3:1: C: Style/Documentation: Missing top-level documentation comment for module UniqueRandom. module UniqueRandom ^^^^^^^^^^^^^^^^^^^ spec/controllers/answers_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [184/25] RSpec.describe AnswersController, type: :controller do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/answers_controller_spec.rb:23:3: C: Metrics/BlockLength: Block has too many lines. [169/25] describe 'POST /answers/create_or_update', js: true do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/answers_controller_spec.rb:24:5: C: Metrics/BlockLength: Block has too many lines. [50/25] context 'standard question type (no question_options and not RDA metadata)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/answers_controller_spec.rb:81:5: C: Metrics/BlockLength: Block has too many lines. [52/25] context 'RDA metadata question type' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/answers_controller_spec.rb:139:5: C: Metrics/BlockLength: Block has too many lines. [53/25] context 'question with question_options' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/concerns/org_selectable_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [82/25] RSpec.describe OrgSelectable do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/concerns/org_selectable_spec.rb:7:5: W: Lint/ConstantDefinitionInBlock: Do not define constants this way within a block. (https://rubystyle.guide#no-constant-definition-in-block) class StubController < ApplicationController ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/concerns/org_selectable_spec.rb:31:3: C: Metrics/BlockLength: Block has too many lines. [60/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/contributors_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [175/25] RSpec.describe ContributorsController, type: :controller do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/contributors_controller_spec.rb:34:3: C: Metrics/BlockLength: Block has too many lines. [61/25] context 'actions' do ... ^^^^^^^^^^^^^^^^^^^^ spec/controllers/contributors_controller_spec.rb:123:3: C: Metrics/BlockLength: Block has too many lines. [84/25] context 'private methods(hash:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/contributors_controller_spec.rb:136:5: C: Metrics/BlockLength: Block has too many lines. [29/25] describe '#process_org(hash:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/contributors_controller_spec.rb:168:5: C: Metrics/BlockLength: Block has too many lines. [40/25] context 'callbacks' do ... ^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/contributors_controller_spec.rb:181:7: C: Metrics/BlockLength: Block has too many lines. [27/25] describe '#fetch_contributor' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/guidance_groups_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [115/25] RSpec.describe GuidanceGroupsController, type: :controller do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/guidances_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [170/25] RSpec.describe GuidancesController, type: :controller do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/guidances_controller_spec.rb:39:3: C: Metrics/BlockLength: Block has too many lines. [26/25] describe 'POST /org/admin/guidance/:id/admin_create (:admin_create)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/guidances_controller_spec.rb:68:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe 'PUT /org/admin/guidance/:id/admin_update (:admin_update)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/guidances_controller_spec.rb:127:3: C: Metrics/BlockLength: Block has too many lines. [30/25] describe 'PUT /org/admin/guidance/:id/admin_update_unpublish (:admin_unpublish)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/notes_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [98/25] RSpec.describe NotesController, type: :controller do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/notes_controller_spec.rb:24:3: C: Metrics/BlockLength: Block has too many lines. [37/25] describe 'POST /notes', js: true do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/orgs_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [166/25] RSpec.describe OrgsController, type: :controller do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/orgs_controller_spec.rb:23:3: C: Metrics/BlockLength: Block has too many lines. [63/25] describe 'PUT /org/admin/:id/admin_update' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/orgs_controller_spec.rb:144:3: C: Metrics/BlockLength: Block has too many lines. [36/25] describe 'POST /orgs' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/registrations_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [36/25] RSpec.describe RegistrationsController, type: :controller do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/registrations_controller_spec.rb:11:3: C: Metrics/BlockLength: Block has too many lines. [30/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/super_admin/orgs_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [70/25] RSpec.describe SuperAdmin::OrgsController, type: :controller do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/controllers/usage_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [109/25] RSpec.describe UsageController, type: :controller do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/csvable_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [28/25] RSpec.describe Csvable do ... ^^^^^^^^^^^^^^^^^^^^^^^^^ spec/csvable_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [26/25] describe '.from_array_of_hashes' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/factories/orgs.rb:34:1: C: Metrics/BlockLength: Block has too many lines. [38/25] FactoryBot.define do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/orgs.rb:35:3: C: Metrics/BlockLength: Block has too many lines. [36/25] factory :org do ... ^^^^^^^^^^^^^^^ spec/factories/perms.rb:13:1: C: Metrics/BlockLength: Block has too many lines. [39/25] FactoryBot.define do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/perms.rb:14:3: C: Metrics/BlockLength: Block has too many lines. [37/25] factory :perm do ... ^^^^^^^^^^^^^^^^ spec/factories/plans.rb:40:1: C: Metrics/BlockLength: Block has too many lines. [48/25] FactoryBot.define do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/plans.rb:41:3: C: Metrics/BlockLength: Block has too many lines. [46/25] factory :plan do ... ^^^^^^^^^^^^^^^^ spec/factories/prefs.rb:13:3: W: Lint/EmptyBlock: Empty block detected. factory :pref do ... ^^^^^^^^^^^^^^^^ spec/factories/question_formats.rb:16:1: C: Metrics/BlockLength: Block has too many lines. [55/25] FactoryBot.define do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/question_formats.rb:17:3: C: Metrics/BlockLength: Block has too many lines. [53/25] factory :question_format do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/factories/questions.rb:31:1: C: Metrics/BlockLength: Block has too many lines. [37/25] FactoryBot.define do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/questions.rb:32:3: C: Metrics/BlockLength: Block has too many lines. [35/25] factory :question do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/roles.rb:26:1: C: Metrics/BlockLength: Block has too many lines. [34/25] FactoryBot.define do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/roles.rb:27:3: C: Metrics/BlockLength: Block has too many lines. [32/25] factory :role do ... ^^^^^^^^^^^^^^^^ spec/factories/templates.rb:35:1: C: Metrics/BlockLength: Block has too many lines. [42/25] FactoryBot.define do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/templates.rb:36:3: C: Metrics/BlockLength: Block has too many lines. [40/25] factory :template do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/users.rb:54:1: C: Metrics/BlockLength: Block has too many lines. [28/25] FactoryBot.define do ... ^^^^^^^^^^^^^^^^^^^^ spec/factories/users.rb:55:3: C: Metrics/BlockLength: Block has too many lines. [26/25] factory :user do ... ^^^^^^^^^^^^^^^^ spec/features/annotations/annotations_editing_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [60/25] RSpec.feature 'Annotations::Editing', type: :feature do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/annotations/annotations_editing_spec.rb:56:7: W: Lint/AmbiguousBlockAssociation: Parenthesize the param change { Annotation.count } to make sure that the block will be associated with the change method call. (https://rubystyle.guide#syntax) expect { click_button 'Save' }.not_to change { Annotation.count } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/feedback_requests_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [28/25] RSpec.describe 'FeedbackRequests', type: :feature do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/locales_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [60/25] RSpec.feature 'Locales', type: :feature, js: true do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/plans/exports_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [115/25] RSpec.describe 'PlansExports', type: :feature, js: true do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/plans_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [44/25] RSpec.describe 'Plans', type: :feature do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/plans_spec.rb:31:3: C: Metrics/BlockLength: Block has too many lines. [32/25] xit 'User creates a new Plan', :js do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/questions/checkbox_questions_spec.rb:5:1: W: Lint/DuplicateRequire: Duplicate require detected. require 'rails_helper' ^^^^^^^^^^^^^^^^^^^^^^ spec/features/questions/dropdown_questions_spec.rb:5:1: W: Lint/DuplicateRequire: Duplicate require detected. require 'rails_helper' ^^^^^^^^^^^^^^^^^^^^^^ spec/features/registrations_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [36/25] RSpec.describe 'Registrations', type: :feature do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/super_admins/merge_org_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [58/25] RSpec.describe 'SuperAdmins Merge Orgs', type: :feature, js: true do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/super_admins/merge_org_spec.rb:30:3: C: Metrics/BlockLength: Block has too many lines. [35/25] scenario 'Super admin merges an Org into another Org' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/super_admins/orgs_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [34/25] RSpec.describe 'SuperAdmins Orgs', type: :feature, js: true do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/templates/templates_copying_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [29/25] RSpec.feature 'Templates::Copying', type: :feature do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/templates/templates_editings_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [35/25] RSpec.feature 'Templates::Editing', type: :feature do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/templates/templates_upgrade_customisations_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [74/25] RSpec.feature 'Templates::UpgradeCustomisations', type: :feature do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/templates/templates_upgrade_customisations_spec.rb:30:3: C: Metrics/BlockLength: Block has too many lines. [54/25] scenario 'Admin upgrades customizations from funder Template', :js do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/features/templates_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [34/25] RSpec.describe 'Templates', type: :feature do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/helpers/identifier_helper_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [44/25] describe IdentifierHelper do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/helpers/identifier_helper_spec.rb:12:3: C: Metrics/BlockLength: Block has too many lines. [38/25] describe '#id_for_display(id:, with_scheme_name)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/helpers/identifier_helper_spec.rb:46:27: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation. (https://rubystyle.guide#string-interpolation) expect(rslt).to eql(@user_scheme.description + ': ' + val) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/helpers/usage_helper_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [104/25] describe UsageHelper do ... ^^^^^^^^^^^^^^^^^^^^^^^ spec/helpers/usage_helper_spec.rb:8:3: C: Metrics/BlockLength: Block has too many lines. [69/25] context 'chart data preparation' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/helpers/usage_helper_spec.rb:23:5: C: Metrics/BlockLength: Block has too many lines. [55/25] describe '#prep_data_for_template_plans_chart' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/helpers/usage_helper_spec.rb:48:7: C: Metrics/BlockLength: Block has too many lines. [46/25] context 'with data' do ... ^^^^^^^^^^^^^^^^^^^^^^ spec/mixins/versionable_model.rb:5:12: W: [Correctable] Lint/OrAssignmentToConstant: Avoid using or-assignment with constants. UUID_REGEX ||= /\A[\w\d]{8}(-[\w\d]{4}){3}-[\w\d]{12}\Z/i.freeze ^^^ spec/mixins/versionable_model.rb:27:7: W: Lint/AmbiguousBlockAssociation: Parenthesize the param change { subject.versionable_id } to make sure that the block will be associated with the change method call. (https://rubystyle.guide#syntax) expect { subject.valid? }.not_to change { subject.versionable_id } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/annotation_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [45/25] RSpec.describe Annotation, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/annotation_spec.rb:28:3: C: Metrics/BlockLength: Block has too many lines. [30/25] describe '#deep_copy' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/answer_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [192/25] RSpec.describe Answer, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/answer_spec.rb:72:3: C: Metrics/BlockLength: Block has too many lines. [63/25] describe '#answered?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/answer_spec.rb:107:5: C: Metrics/BlockLength: Block has too many lines. [38/25] describe 'option based question' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/answer_spec.rb:191:3: C: Metrics/BlockLength: Block has too many lines. [27/25] describe '#answer_hash' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/api_client_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [48/25] RSpec.describe ApiClient, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/concerns/date_rangeable_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [49/25] RSpec.describe DateRangeable do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/concerns/date_rangeable_spec.rb:17:3: C: Metrics/BlockLength: Block has too many lines. [38/25] context 'class methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/concerns/identifiable_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [83/25] RSpec.describe Identifiable do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/concerns/identifiable_spec.rb:15:3: C: Metrics/BlockLength: Block has too many lines. [31/25] context 'class methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/concerns/identifiable_spec.rb:16:5: C: Metrics/BlockLength: Block has too many lines. [29/25] describe '#from_identifiers(array:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/concerns/identifiable_spec.rb:49:3: C: Metrics/BlockLength: Block has too many lines. [41/25] context 'instance methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/contributor_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [123/25] RSpec.describe Contributor, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/contributor_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [27/25] context 'validations' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/contributor_spec.rb:45:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '==(other)' do ... ^^^^^^^^^^^^^^^^^^^^^^^ spec/models/contributor_spec.rb:77:3: C: Metrics/BlockLength: Block has too many lines. [57/25] describe 'merge(other)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/guidance_group_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [157/25] RSpec.describe GuidanceGroup, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/guidance_group_spec.rb:26:3: C: Metrics/BlockLength: Block has too many lines. [51/25] describe '.can_view?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/guidance_group_spec.rb:99:3: C: Metrics/BlockLength: Block has too many lines. [90/25] describe '.all_viewable' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/guidance_group_spec.rb:177:5: C: Metrics/BlockLength: Block has too many lines. [34/25] context ':merge!(to_be_merged:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/guidance_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [201/25] RSpec.describe Guidance, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/guidance_spec.rb:30:3: C: Metrics/BlockLength: Block has too many lines. [79/25] describe '.can_view?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/guidance_spec.rb:133:3: C: Metrics/BlockLength: Block has too many lines. [83/25] describe '.all_viewable' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/identifier_scheme_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [57/25] RSpec.describe IdentifierScheme, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/identifier_scheme_spec.rb:22:3: C: Metrics/BlockLength: Block has too many lines. [26/25] context 'scopes' do ... ^^^^^^^^^^^^^^^^^^^ spec/models/identifier_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [197/25] RSpec.describe Identifier, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/identifier_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [58/25] context 'validations' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/identifier_spec.rb:11:5: C: Metrics/BlockLength: Block has too many lines. [54/25] describe 'uniqueness' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/identifier_spec.rb:115:3: C: Metrics/BlockLength: Block has too many lines. [46/25] describe '#identifier_format' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/identifier_spec.rb:190:3: C: Metrics/BlockLength: Block has too many lines. [31/25] describe '#value=(val)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/language_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [90/25] RSpec.describe Language, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/language_spec.rb:88:3: C: Metrics/BlockLength: Block has too many lines. [29/25] describe '#abbreviation' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/notification_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [130/25] RSpec.describe Notification, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/notification_spec.rb:36:3: C: Metrics/BlockLength: Block has too many lines. [33/25] describe '.active' do ... ^^^^^^^^^^^^^^^^^^^^^ spec/models/notification_spec.rb:80:3: C: Metrics/BlockLength: Block has too many lines. [39/25] describe '.active_per_user' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/notification_spec.rb:146:3: C: Metrics/BlockLength: Block has too many lines. [36/25] describe '#acknowledged?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [545/25] RSpec.describe Org, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:64:3: C: Metrics/BlockLength: Block has too many lines. [32/25] context 'scopes' do ... ^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:115:3: C: Metrics/BlockLength: Block has too many lines. [35/25] describe '#org_type_to_s' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:124:5: C: Metrics/BlockLength: Block has too many lines. [28/25] context 'organisation present' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:240:3: C: Metrics/BlockLength: Block has too many lines. [42/25] describe '#org_admins' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:296:3: C: Metrics/BlockLength: Block has too many lines. [37/25] describe '#plans' do ... ^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:347:3: C: Metrics/BlockLength: Block has too many lines. [58/25] describe '#org_admin_plans' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:460:3: C: Metrics/BlockLength: Block has too many lines. [91/25] context ':merge!(to_be_merged:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:557:3: C: Metrics/BlockLength: Block has too many lines. [115/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:558:5: C: Metrics/BlockLength: Block has too many lines. [35/25] describe ':merge_attributes!(to_be_merged:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/org_spec.rb:625:5: C: Metrics/BlockLength: Block has too many lines. [27/25] describe ':merge_guidance_groups!(to_be_merged:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/perm_spec.rb:22:1: C: Metrics/BlockLength: Block has too many lines. [250/25] RSpec.describe Perm, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/perm_spec.rb:36:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '.add_orgs' do ... ^^^^^^^^^^^^^^^^^^^^^^^ spec/models/perm_spec.rb:76:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '.change_affiliation' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/perm_spec.rb:116:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '.grant_permissions' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/perm_spec.rb:156:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '.modify_templates' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/perm_spec.rb:196:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '.modify_guidance' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/perm_spec.rb:236:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '.use_api' do ... ^^^^^^^^^^^^^^^^^^^^^^ spec/models/perm_spec.rb:276:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '.change_org_details' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/perm_spec.rb:316:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '.grant_api' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/phase_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [130/25] RSpec.describe Phase, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/phase_spec.rb:64:3: C: Metrics/BlockLength: Block has too many lines. [50/25] describe '#deep_copy' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/phase_spec.rb:71:5: C: Metrics/BlockLength: Block has too many lines. [27/25] context 'when no options are provided' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [1056/25] describe Plan do ... ^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:10:3: C: Metrics/BlockLength: Block has too many lines. [26/25] context 'validations' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:164:3: C: Metrics/BlockLength: Block has too many lines. [88/25] describe '.organisationally_or_publicly_visible' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:335:3: C: Metrics/BlockLength: Block has too many lines. [29/25] describe '.load_for_phase' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:414:3: C: Metrics/BlockLength: Block has too many lines. [33/25] describe '.search' do ... ^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:483:3: C: Metrics/BlockLength: Block has too many lines. [33/25] describe '#answer' do ... ^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:566:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '#request_feedback' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:590:7: W: Lint/AmbiguousBlockAssociation: Parenthesize the param change { ActionMailer::Base.deliveries.size } to make sure that the block will be associated with the change method call. (https://rubystyle.guide#syntax) expect { subject }.not_to change { ActionMailer::Base.deliveries.size } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:606:3: C: Metrics/BlockLength: Block has too many lines. [34/25] describe '#complete_feedback' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:637:7: W: Lint/AmbiguousBlockAssociation: Parenthesize the param change { ActionMailer::Base.deliveries.size } to make sure that the block will be associated with the change method call. (https://rubystyle.guide#syntax) expect { subject }.not_to change { ActionMailer::Base.deliveries.size } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:654:3: W: Lint/EmptyBlock: Empty block detected. describe '#guidance_by_question_as_hash' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:657:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '#editable_by?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:699:3: C: Metrics/BlockLength: Block has too many lines. [110/25] describe '#readable_by?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:738:5: C: Metrics/BlockLength: Block has too many lines. [59/25] context 'non-admin user' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:839:3: C: Metrics/BlockLength: Block has too many lines. [61/25] describe '#commentable_by?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:922:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '#administerable_by?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:1044:3: C: Metrics/BlockLength: Block has too many lines. [51/25] describe '#add_user' do ... ^^^^^^^^^^^^^^^^^^^^^^^ spec/models/plan_spec.rb:1340:3: C: Metrics/BlockLength: Block has too many lines. [34/25] describe '#grant association sanity checks' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/question_format_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [58/25] RSpec.describe QuestionFormat, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/question_option_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [55/25] RSpec.describe QuestionOption, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/question_option_spec.rb:42:3: C: Metrics/BlockLength: Block has too many lines. [27/25] describe '#deep_copy' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/question_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [245/25] RSpec.describe Question, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/question_spec.rb:97:3: C: Metrics/BlockLength: Block has too many lines. [69/25] describe '#deep_copy' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/question_spec.rb:111:5: C: Metrics/BlockLength: Block has too many lines. [32/25] context 'when no options are provided' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/question_spec.rb:224:3: C: Metrics/BlockLength: Block has too many lines. [37/25] describe '#guidance_annotation' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/question_spec.rb:274:3: C: Metrics/BlockLength: Block has too many lines. [43/25] describe '#annotations_per_org' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/research_output_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [49/25] RSpec.describe ResearchOutput, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/role_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [59/25] RSpec.describe Role, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/role_spec.rb:31:3: C: Metrics/BlockLength: Block has too many lines. [40/25] describe '.deactivate!' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/section_sorter_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [110/25] RSpec.describe SectionSorter, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/section_sorter_spec.rb:6:3: W: Lint/ConstantDefinitionInBlock: Do not define constants this way within a block. (https://rubystyle.guide#no-constant-definition-in-block) StubSection = Struct.new(:number, :modifiable, :id) do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/section_sorter_spec.rb:22:3: C: Metrics/BlockLength: Block has too many lines. [96/25] describe '#sort!' do ... ^^^^^^^^^^^^^^^^^^^^ spec/models/section_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [57/25] RSpec.describe Section, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/stat_created_plan_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [95/25] RSpec.describe StatCreatedPlan, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/stat_created_plan_spec.rb:17:3: C: Metrics/BlockLength: Block has too many lines. [59/25] describe '.to_csv' do ... ^^^^^^^^^^^^^^^^^^^^^ spec/models/stat_created_plan_spec.rb:25:5: C: Metrics/BlockLength: Block has too many lines. [51/25] context 'when instances' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/stat_created_plan_spec.rb:49:7: C: Metrics/BlockLength: Block has too many lines. [30/25] context 'when details by template is true' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/stat_created_plan_spec.rb:50:9: C: Metrics/BlockLength: Block has too many lines. [28/25] it 'returns counts by_template in a comma-separated row' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/stat_joined_user_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [39/25] RSpec.describe StatJoinedUser, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [933/25] RSpec.describe Template, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:88:3: C: Metrics/BlockLength: Block has too many lines. [26/25] describe '.default' do ... ^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:123:3: C: Metrics/BlockLength: Block has too many lines. [40/25] describe '.latest_version' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:180:3: C: Metrics/BlockLength: Block has too many lines. [33/25] describe '.published' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:224:3: C: Metrics/BlockLength: Block has too many lines. [43/25] describe '.latest_customized_version' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:283:3: C: Metrics/BlockLength: Block has too many lines. [29/25] describe '.latest_version_per_org' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:329:3: C: Metrics/BlockLength: Block has too many lines. [43/25] describe '.latest_customized_version_per_org' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:388:3: C: Metrics/BlockLength: Block has too many lines. [35/25] describe '.families' do ... ^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:436:3: C: Metrics/BlockLength: Block has too many lines. [38/25] describe '.latest_customizable' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:590:3: C: Metrics/BlockLength: Block has too many lines. [45/25] describe '.live' do ... ^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:650:3: C: Metrics/BlockLength: Block has too many lines. [31/25] describe '.find_or_generate_version!' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:694:3: C: Metrics/BlockLength: Block has too many lines. [39/25] describe '#deep_copy' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:821:3: C: Metrics/BlockLength: Block has too many lines. [32/25] describe '#customize?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:873:3: C: Metrics/BlockLength: Block has too many lines. [26/25] describe '#upgrade_customization?' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:910:3: C: Metrics/BlockLength: Block has too many lines. [29/25] describe '#draft?' do ... ^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:978:3: C: Metrics/BlockLength: Block has too many lines. [32/25] describe '#generate_copy!' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:1054:3: C: Metrics/BlockLength: Block has too many lines. [38/25] describe '#customize!' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:1111:3: C: Metrics/BlockLength: Block has too many lines. [54/25] describe '#upgrade_customization!' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/template_spec.rb:1184:3: C: Metrics/BlockLength: Block has too many lines. [76/25] describe '#publishability' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/theme_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [36/25] RSpec.describe Theme, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/tracker_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [28/25] RSpec.describe Tracker, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/tracker_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [26/25] describe 'creation' do ... ^^^^^^^^^^^^^^^^^^^^^^ spec/models/user_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [420/25] RSpec.describe User, type: :model do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/user_spec.rb:90:3: C: Metrics/BlockLength: Block has too many lines. [50/25] describe '#save' do ... ^^^^^^^^^^^^^^^^^^^ spec/models/user_spec.rb:186:3: C: Metrics/BlockLength: Block has too many lines. [52/25] describe '#name' do ... ^^^^^^^^^^^^^^^^^^^ spec/models/user_spec.rb:429:12: W: Lint/AmbiguousBlockAssociation: Parenthesize the param change { user.api_token } to make sure that the block will be associated with the change method call. (https://rubystyle.guide#syntax) it { expect { subject }.not_to change { user.api_token } } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/user_spec.rb:441:12: W: Lint/AmbiguousBlockAssociation: Parenthesize the param change { user.api_token } to make sure that the block will be associated with the change method call. (https://rubystyle.guide#syntax) it { expect { subject }.not_to change { user.api_token } } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/user_spec.rb:451:12: W: Lint/AmbiguousBlockAssociation: Parenthesize the param change { user.api_token } to make sure that the block will be associated with the change method call. (https://rubystyle.guide#syntax) it { expect { subject }.to change { user.api_token } } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/user_spec.rb:457:12: W: Lint/AmbiguousBlockAssociation: Parenthesize the param change { user.api_token } to make sure that the block will be associated with the change method call. (https://rubystyle.guide#syntax) it { expect { subject }.to change { user.api_token } } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/user_spec.rb:463:12: W: Lint/AmbiguousBlockAssociation: Parenthesize the param change { user.api_token } to make sure that the block will be associated with the change method call. (https://rubystyle.guide#syntax) it { expect { subject }.not_to change { user.api_token } } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/models/user_spec.rb:498:3: C: Metrics/BlockLength: Block has too many lines. [32/25] describe '#get_preferences' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/policies/usage_policy_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [38/25] RSpec.describe UsagePolicy, type: :policy do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/api/v1/contributor_presenter_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [29/25] RSpec.describe Api::V1::ContributorPresenter do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/api/v1/org_presenter_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [27/25] RSpec.describe Api::V1::OrgPresenter do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/api/v1/pagination_presenter_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [158/25] RSpec.describe Api::V1::PaginationPresenter do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/api/v1/pagination_presenter_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [56/25] describe '#url_without_pagination' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/api/v1/pagination_presenter_spec.rb:138:3: C: Metrics/BlockLength: Block has too many lines. [32/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/api/v1/pagination_presenter_spec.rb:139:5: C: Metrics/BlockLength: Block has too many lines. [30/25] describe '#total_pages' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/api/v1/plan_presenter_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [34/25] RSpec.describe Api::V1::PlanPresenter do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/api/v1/plan_presenter_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [32/25] describe '#initialize(plan:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/identifier_presenter_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [77/25] RSpec.describe IdentifierPresenter do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/identifier_presenter_spec.rb:51:3: C: Metrics/BlockLength: Block has too many lines. [36/25] context '#schemes' do ... ^^^^^^^^^^^^^^^^^^^^^ spec/presenters/org_selection_presenter_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [40/25] RSpec.describe OrgSelectionPresenter do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/super_admin/orgs/merge_presenter_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [272/25] RSpec.describe SuperAdmin::Orgs::MergePresenter do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/super_admin/orgs/merge_presenter_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [30/25] before(:each) do ... ^^^^^^^^^^^^^^^^ spec/presenters/super_admin/orgs/merge_presenter_spec.rb:40:3: C: Metrics/BlockLength: Block has too many lines. [27/25] describe ':initialize(from_org:, to_org:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/super_admin/orgs/merge_presenter_spec.rb:70:3: C: Metrics/BlockLength: Block has too many lines. [209/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/super_admin/orgs/merge_presenter_spec.rb:71:5: C: Metrics/BlockLength: Block has too many lines. [26/25] describe ':prepare_org(org:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/super_admin/orgs/merge_presenter_spec.rb:123:5: C: Metrics/BlockLength: Block has too many lines. [80/25] describe ':diff_from_and_to(category:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/presenters/super_admin/orgs/merge_presenter_spec.rb:239:5: C: Metrics/BlockLength: Block has too many lines. [43/25] describe ':mergeable_column?(column:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/authentication_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [36/25] RSpec.describe Api::V1::AuthenticationController, type: :request do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/authentication_controller_spec.rb:10:3: C: Metrics/BlockLength: Block has too many lines. [31/25] context 'actions' do ... ^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/authentication_controller_spec.rb:11:5: C: Metrics/BlockLength: Block has too many lines. [29/25] describe 'POST /api/v1/authenticate' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/base_api_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [93/25] RSpec.describe Api::V1::BaseApiController, type: :request do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/base_api_controller_spec.rb:27:3: C: Metrics/BlockLength: Block has too many lines. [72/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [339/25] RSpec.describe Api::V1::PlansController, type: :request do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:8:3: C: Metrics/BlockLength: Block has too many lines. [292/25] context 'ApiClient' do ... ^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:37:5: C: Metrics/BlockLength: Block has too many lines. [266/25] describe 'POST /api/v1/plans - create' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:47:7: C: Metrics/BlockLength: Block has too many lines. [80/25] context 'minimal JSON' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:103:9: C: Metrics/BlockLength: Block has too many lines. [28/25] context 'plan inspection' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:136:7: C: Metrics/BlockLength: Block has too many lines. [175/25] context 'complete JSON' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:147:9: C: Metrics/BlockLength: Block has too many lines. [165/25] context 'plan inspection' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:176:11: C: Metrics/BlockLength: Block has too many lines. [59/25] context 'contact inspection' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:243:11: C: Metrics/BlockLength: Block has too many lines. [52/25] context 'contributor inspection' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:337:3: C: Metrics/BlockLength: Block has too many lines. [42/25] context 'User' do ... ^^^^^^^^^^^^^^^^^ spec/requests/api/v1/plans_controller.rb:338:5: C: Metrics/BlockLength: Block has too many lines. [40/25] describe 'GET /api/v1/plan/:id - show' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/templates_controller_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [68/25] RSpec.describe Api::V1::TemplatesController, type: :request do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/templates_controller_spec.rb:8:3: C: Metrics/BlockLength: Block has too many lines. [27/25] context 'ApiClient' do ... ^^^^^^^^^^^^^^^^^^^^^^ spec/requests/api/v1/templates_controller_spec.rb:42:3: C: Metrics/BlockLength: Block has too many lines. [36/25] context 'User' do ... ^^^^^^^^^^^^^^^^^ spec/requests/api/v1/templates_controller_spec.rb:47:5: C: Metrics/BlockLength: Block has too many lines. [31/25] describe 'GET /api/v1/templates - index' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authentication_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [298/25] RSpec.describe Api::V1::Auth::Jwt::AuthenticationService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authentication_service_spec.rb:11:3: C: Metrics/BlockLength: Block has too many lines. [133/25] context 'instance methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authentication_service_spec.rb:12:5: C: Metrics/BlockLength: Block has too many lines. [51/25] describe '#initialize(json:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authentication_service_spec.rb:66:5: C: Metrics/BlockLength: Block has too many lines. [78/25] describe '#call' do ... ^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authentication_service_spec.rb:154:3: C: Metrics/BlockLength: Block has too many lines. [157/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authentication_service_spec.rb:155:5: C: Metrics/BlockLength: Block has too many lines. [38/25] describe '#client' do ... ^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authentication_service_spec.rb:222:5: C: Metrics/BlockLength: Block has too many lines. [29/25] describe '#authenticate_user' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authentication_service_spec.rb:255:5: C: Metrics/BlockLength: Block has too many lines. [38/25] describe '#parse_client' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authorization_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [63/25] RSpec.describe Api::V1::Auth::Jwt::AuthorizationService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/authorization_service_spec.rb:24:3: C: Metrics/BlockLength: Block has too many lines. [46/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/auth/jwt/json_web_token_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [42/25] RSpec.describe Api::V1::Auth::Jwt::JsonWebToken do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/contextual_error_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [115/25] RSpec.describe Api::V1::ContextualErrorService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/contextual_error_service_spec.rb:42:3: C: Metrics/BlockLength: Block has too many lines. [62/25] describe 'contextualize(errors:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/conversion_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [52/25] RSpec.describe Api::V1::ConversionService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/contributor_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [150/25] RSpec.describe Api::V1::Deserialization::Contributor do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/contributor_spec.rb:32:3: C: Metrics/BlockLength: Block has too many lines. [32/25] describe ':deserialize(json: {})' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/contributor_spec.rb:67:3: C: Metrics/BlockLength: Block has too many lines. [93/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/contributor_spec.rb:68:5: C: Metrics/BlockLength: Block has too many lines. [36/25] describe ':find_or_initialize(id_json:, json: {})' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/contributor_spec.rb:132:5: C: Metrics/BlockLength: Block has too many lines. [30/25] describe ':assign_roles(contributor:, json:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/funding_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [34/25] RSpec.describe Api::V1::Deserialization::Funding do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/identifier_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [45/25] RSpec.describe Api::V1::Deserialization::Identifier do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/identifier_spec.rb:13:3: C: Metrics/BlockLength: Block has too many lines. [31/25] describe ':deserialize(class_name:, json: {})' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/org_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [88/25] RSpec.describe Api::V1::Deserialization::Org do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/org_spec.rb:21:3: C: Metrics/BlockLength: Block has too many lines. [46/25] describe '#deserialize(json: {})' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/org_spec.rb:71:3: C: Metrics/BlockLength: Block has too many lines. [26/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/plan_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [236/25] RSpec.describe Api::V1::Deserialization::Plan do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/plan_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [52/25] before(:each) do ... ^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/plan_spec.rb:68:3: C: Metrics/BlockLength: Block has too many lines. [26/25] describe '#deserialize!(json: {})' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/plan_spec.rb:98:3: C: Metrics/BlockLength: Block has too many lines. [152/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/plan_spec.rb:99:5: C: Metrics/BlockLength: Block has too many lines. [36/25] describe ':find_or_initialize(id_json:, json: {})' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization/plan_spec.rb:138:5: C: Metrics/BlockLength: Block has too many lines. [43/25] describe '#deserialize_project(plan:, json:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [202/25] RSpec.describe Api::V1::DeserializationService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization_service_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [47/25] describe 'object_from_identifier(clazz:, json:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization_service_spec.rb:56:3: C: Metrics/BlockLength: Block has too many lines. [39/25] describe ':attach_identifier(object:, json:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization_service_spec.rb:150:3: C: Metrics/BlockLength: Block has too many lines. [33/25] describe 'doi?(value:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/deserialization_service_spec.rb:187:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe ':safe_date(value:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/json_validation_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [269/25] RSpec.describe Api::V1::JsonValidationService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/json_validation_service_spec.rb:110:3: C: Metrics/BlockLength: Block has too many lines. [54/25] describe 'validation_errors(json:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/json_validation_service_spec.rb:167:3: C: Metrics/BlockLength: Block has too many lines. [47/25] describe ':contributor_validation_errors(json:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/json_validation_service_spec.rb:217:3: C: Metrics/BlockLength: Block has too many lines. [33/25] describe ':funding_validation_errors(json:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/json_validation_service_spec.rb:253:3: C: Metrics/BlockLength: Block has too many lines. [29/25] describe ':org_validation_errors(json:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/persistence_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [214/25] RSpec.describe Api::V1::PersistenceService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/persistence_service_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [67/25] describe 'safe_save(plan:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/persistence_service_spec.rb:76:3: C: Metrics/BlockLength: Block has too many lines. [143/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/persistence_service_spec.rb:103:5: C: Metrics/BlockLength: Block has too many lines. [27/25] describe 'safe_save_org(org:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/persistence_service_spec.rb:133:5: C: Metrics/BlockLength: Block has too many lines. [34/25] describe 'safe_save_contributor(contributor:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/persistence_service_spec.rb:170:5: C: Metrics/BlockLength: Block has too many lines. [52/25] describe 'deduplicate_contributors(contributors:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/api/v1/validation_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [98/25] RSpec.describe Api::V1::ValidationService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/base_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [118/25] RSpec.describe ExternalApis::BaseService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/base_service_spec.rb:46:3: C: Metrics/BlockLength: Block has too many lines. [76/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/base_service_spec.rb:69:5: C: Metrics/BlockLength: Block has too many lines. [26/25] context '#http_get' do ... ^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/ror_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [338/25] RSpec.describe ExternalApis::RorService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/ror_service_spec.rb:23:3: C: Metrics/BlockLength: Block has too many lines. [94/25] describe '#search' do ... ^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/ror_service_spec.rb:65:5: C: Metrics/BlockLength: Block has too many lines. [55/25] context 'Successful response from API' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/ror_service_spec.rb:66:7: C: Metrics/BlockLength: Block has too many lines. [36/25] before(:each) do ... ^^^^^^^^^^^^^^^^ spec/services/external_apis/ror_service_spec.rb:127:3: C: Metrics/BlockLength: Block has too many lines. [224/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/ror_service_spec.rb:128:5: C: Metrics/BlockLength: Block has too many lines. [30/25] describe '#query_ror' do ... ^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/ror_service_spec.rb:162:5: C: Metrics/BlockLength: Block has too many lines. [26/25] describe '#query_string' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/ror_service_spec.rb:191:5: C: Metrics/BlockLength: Block has too many lines. [67/25] describe '#process_pages' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/external_apis/ror_service_spec.rb:293:5: C: Metrics/BlockLength: Block has too many lines. [30/25] describe '#org_name' do ... ^^^^^^^^^^^^^^^^^^^^^^^ spec/services/locale_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [72/25] RSpec.describe LocaleService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/create_created_plan_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [171/25] RSpec.describe Org::CreateCreatedPlanService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/create_created_plan_service_spec.rb:27:3: C: Metrics/BlockLength: Block has too many lines. [46/25] before(:each) do ... ^^^^^^^^^^^^^^^^ spec/services/org/create_created_plan_service_spec.rb:82:3: C: Metrics/BlockLength: Block has too many lines. [95/25] describe '.call' do ... ^^^^^^^^^^^^^^^^^^^ spec/services/org/create_created_plan_service_spec.rb:83:5: C: Metrics/BlockLength: Block has too many lines. [44/25] context 'when org is passed' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/create_created_plan_service_spec.rb:138:5: C: Metrics/BlockLength: Block has too many lines. [47/25] context 'when no org is passed' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/create_joined_user_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [52/25] RSpec.describe Org::CreateJoinedUserService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/create_joined_user_service_spec.rb:24:3: C: Metrics/BlockLength: Block has too many lines. [34/25] describe '.call' do ... ^^^^^^^^^^^^^^^^^^^ spec/services/org/create_last_month_created_plan_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [158/25] RSpec.describe Org::CreateLastMonthCreatedPlanService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/create_last_month_created_plan_service_spec.rb:49:3: C: Metrics/BlockLength: Block has too many lines. [114/25] describe '.call' do ... ^^^^^^^^^^^^^^^^^^^ spec/services/org/create_last_month_created_plan_service_spec.rb:50:5: C: Metrics/BlockLength: Block has too many lines. [54/25] context 'when org is passed' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/create_last_month_created_plan_service_spec.rb:121:5: C: Metrics/BlockLength: Block has too many lines. [56/25] context 'when no org is passed' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/create_last_month_joined_user_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [43/25] RSpec.describe Org::CreateLastMonthJoinedUserService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/create_last_month_joined_user_service_spec.rb:15:3: C: Metrics/BlockLength: Block has too many lines. [32/25] describe '.call' do ... ^^^^^^^^^^^^^^^^^^^ spec/services/org/total_count_created_plan_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [27/25] RSpec.describe Org::TotalCountCreatedPlanService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org/total_count_joined_user_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [27/25] RSpec.describe Org::TotalCountJoinedUserService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org_selection/hash_to_org_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [212/25] RSpec.describe OrgSelection::HashToOrgService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org_selection/hash_to_org_service_spec.rb:52:3: C: Metrics/BlockLength: Block has too many lines. [30/25] describe '#to_identifiers(hash:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org_selection/hash_to_org_service_spec.rb:86:3: C: Metrics/BlockLength: Block has too many lines. [135/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org_selection/hash_to_org_service_spec.rb:144:20: C: [Correctable] Style/RedundantArgument: Argument ' ' is redundant because it is implied by default. expected = @name.split(' ').map { |i| i[0].upcase }.join ^^^^^^^^^^^^^^^^ spec/services/org_selection/org_to_hash_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [26/25] RSpec.describe OrgSelection::OrgToHashService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org_selection/search_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [331/25] RSpec.describe OrgSelection::SearchService do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org_selection/search_service_spec.rb:120:3: C: Metrics/BlockLength: Block has too many lines. [223/25] context 'private methods' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org_selection/search_service_spec.rb:204:5: C: Metrics/BlockLength: Block has too many lines. [28/25] describe '#sort(array:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org_selection/search_service_spec.rb:285:5: C: Metrics/BlockLength: Block has too many lines. [31/25] describe '#weigh(search_term:, item_name:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/org_selection/search_service_spec.rb:319:5: C: Metrics/BlockLength: Block has too many lines. [35/25] describe '#filter(array:)' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/template/upgrade_customization_service_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [167/25] RSpec.describe 'Template::UpgradeCustomizationService', type: :service do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/services/template/upgrade_customization_service_spec.rb:6:3: C: Metrics/BlockLength: Block has too many lines. [165/25] describe '.call' do ... ^^^^^^^^^^^^^^^^^^^ spec/services/template/upgrade_customization_service_spec.rb:27:5: C: Metrics/BlockLength: Block has too many lines. [32/25] context 'when template is a customization of a published funder template' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/spec_helper.rb:28:1: C: Metrics/BlockLength: Block has too many lines. [34/25] RSpec.configure do |config| ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/support/database_cleaner.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [32/25] RSpec.configure do |config| ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/support/helpers/capybara_helper.rb:9:40: C: [Correctable] Style/AndOr: Use && instead of and. (https://rubystyle.guide#no-and-or-or) elsif browser.respond_to?(:manage) and browser.manage.respond_to?(:delete_all_cookies) ^^^ spec/support/helpers/roles_helper.rb:4:18: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use administrator: false instead of administrator = false. (https://rubystyle.guide#boolean-keyword-arguments) def build_plan(administrator = false, editor = false, commenter = false) ^^^^^^^^^^^^^^^^^^^^^ spec/support/helpers/roles_helper.rb:4:41: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use editor: false instead of editor = false. (https://rubystyle.guide#boolean-keyword-arguments) def build_plan(administrator = false, editor = false, commenter = false) ^^^^^^^^^^^^^^ spec/support/helpers/roles_helper.rb:4:57: C: Style/OptionalBooleanParameter: Prefer keyword arguments for arguments with a boolean default value; use commenter: false instead of commenter = false. (https://rubystyle.guide#boolean-keyword-arguments) def build_plan(administrator = false, editor = false, commenter = false) ^^^^^^^^^^^^^^^^^ spec/views/api/v1/_standard_response.json_jbuilder_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [143/25] describe 'api/v1/_standard_response.json.jbuilder' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/_standard_response.json_jbuilder_spec.rb:19:3: C: Metrics/BlockLength: Block has too many lines. [29/25] describe 'standard response items - Also the same as: GET /heartbeat' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/_standard_response.json_jbuilder_spec.rb:52:3: C: Metrics/BlockLength: Block has too many lines. [100/25] context 'responses with pagination' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/contributors/_show.json.jbuilder_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [70/25] describe 'api/v1/contributors/_show.json.jbuilder' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/contributors/_show.json.jbuilder_spec.rb:16:3: C: Metrics/BlockLength: Block has too many lines. [28/25] describe 'includes all of the Contributor attributes' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/contributors/_show.json.jbuilder_spec.rb:51:3: C: Metrics/BlockLength: Block has too many lines. [29/25] describe 'includes all of the Contact attributes' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/orgs/_show.json.jbuilder_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [32/25] describe 'api/v1/orgs/_show.json.jbuilder' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/plans/_funding.json.jbuilder_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [45/25] describe 'api/v1/plans/_funding.json.jbuilder' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/plans/_funding.json.jbuilder_spec.rb:22:3: C: Metrics/BlockLength: Block has too many lines. [29/25] describe 'includes all of the funding attributes' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/plans/_show.json.jbuilder_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [86/25] describe 'api/v1/plans/_show.json.jbuilder' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/plans/_show.json.jbuilder_spec.rb:15:3: C: Metrics/BlockLength: Block has too many lines. [64/25] describe 'includes all of the DMP attributes' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/templates/index.json.jbuilder_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [44/25] describe 'api/v1/templates/index.json.jbuilder' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ spec/views/api/v1/token.json.jbuilder_spec.rb:5:1: C: Metrics/BlockLength: Block has too many lines. [32/25] describe 'api/v1/token.json.jbuilder' do ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 529 files inspected, 793 offenses detected, 59 more offenses can be corrected with `rubocop -A` for entire repo. then fixed up remaining issues with controllers, policies, presenters --- .rubocop.yml | 11 +- Gemfile | 169 ++- Rakefile | 2 +- app/channels/application_cable/channel.rb | 3 - app/channels/application_cable/connection.rb | 3 - app/controllers/answers_controller.rb | 44 +- app/controllers/api/v0/base_controller.rb | 213 ++-- .../api/v0/departments_controller.rb | 123 +- .../api/v0/guidance_groups_controller.rb | 35 +- app/controllers/api/v0/plans_controller.rb | 236 ++-- .../api/v0/statistics_controller.rb | 449 ++++--- .../api/v0/templates_controller.rb | 101 +- .../api/v1/authentication_controller.rb | 15 +- app/controllers/api/v1/base_api_controller.rb | 18 +- app/controllers/api/v1/plans_controller.rb | 34 +- .../api/v1/templates_controller.rb | 11 +- app/controllers/application_controller.rb | 70 +- .../concerns/allowed_question_formats.rb | 6 +- .../concerns/conditional_user_mailer.rb | 10 +- app/controllers/concerns/org_selectable.rb | 4 +- app/controllers/concerns/paginable.rb | 56 +- app/controllers/concerns/template_methods.rb | 5 +- app/controllers/concerns/versionable.rb | 24 +- app/controllers/contacts_controller.rb | 56 +- app/controllers/contributors_controller.rb | 35 +- .../feedback_requests_controller.rb | 7 +- app/controllers/guidance_groups_controller.rb | 29 +- app/controllers/guidances_controller.rb | 41 +- app/controllers/home_controller.rb | 7 +- app/controllers/identifiers_controller.rb | 16 +- app/controllers/notes_controller.rb | 65 +- .../org_admin/conditions_controller.rb | 57 +- .../org_admin/departments_controller.rb | 125 +- .../org_admin/phase_versions_controller.rb | 31 +- .../org_admin/phases_controller.rb | 54 +- app/controllers/org_admin/plans_controller.rb | 139 +-- .../org_admin/question_options_controller.rb | 15 +- .../org_admin/questions_controller.rb | 52 +- .../org_admin/sections_controller.rb | 39 +- .../org_admin/template_copies_controller.rb | 41 +- ...late_customization_transfers_controller.rb | 55 +- .../template_customizations_controller.rb | 43 +- .../org_admin/templates_controller.rb | 148 ++- app/controllers/org_admin/users_controller.rb | 15 +- app/controllers/orgs_controller.rb | 66 +- .../paginable/contributors_controller.rb | 9 +- .../paginable/departments_controller.rb | 45 +- .../paginable/guidance_groups_controller.rb | 27 +- .../paginable/guidances_controller.rb | 29 +- .../paginable/notifications_controller.rb | 19 +- app/controllers/paginable/orgs_controller.rb | 27 +- app/controllers/paginable/plans_controller.rb | 119 +- .../paginable/templates_controller.rb | 196 +-- .../paginable/themes_controller.rb | 19 +- app/controllers/paginable/users_controller.rb | 59 +- app/controllers/passwords_controller.rb | 3 +- app/controllers/plan_exports_controller.rb | 32 +- app/controllers/plans_controller.rb | 128 +- app/controllers/public_pages_controller.rb | 40 +- .../question_formats_controller.rb | 5 +- app/controllers/registrations_controller.rb | 157 +-- .../research_projects_controller.rb | 7 +- app/controllers/roles_controller.rb | 77 +- app/controllers/session_locales_controller.rb | 3 +- app/controllers/sessions_controller.rb | 13 +- app/controllers/settings.rb | 4 +- app/controllers/settings/plans_controller.rb | 15 +- app/controllers/static_pages_controller.rb | 18 +- .../super_admin/api_clients_controller.rb | 26 +- .../super_admin/notifications_controller.rb | 29 +- .../super_admin/org_swaps_controller.rb | 64 +- .../super_admin/orgs_controller.rb | 45 +- .../super_admin/themes_controller.rb | 21 +- .../super_admin/users_controller.rb | 41 +- .../template_options_controller.rb | 19 +- app/controllers/usage_controller.rb | 59 +- app/controllers/usage_downloads_controller.rb | 5 +- .../users/invitations_controller.rb | 97 +- .../users/omniauth_callbacks_controller.rb | 139 +-- app/controllers/users_controller.rb | 46 +- app/helpers/annotations_helper.rb | 2 - app/helpers/application_helper.rb | 2 - app/helpers/conditions_helper.rb | 46 +- .../customizable_template_link_helper.rb | 12 +- app/helpers/exports_helper.rb | 16 +- app/helpers/feedbacks_helper.rb | 12 +- app/helpers/identifier_helper.rb | 10 +- app/helpers/languages_helper.rb | 4 +- app/helpers/mailer_helper.rb | 22 +- app/helpers/manifests_helper.rb | 4 +- app/helpers/notifications_helper.rb | 12 +- app/helpers/orgs_helper.rb | 13 +- app/helpers/paginable_helper.rb | 2 - app/helpers/perms_helper.rb | 20 +- app/helpers/plans_helper.rb | 26 +- app/helpers/sections_helper.rb | 2 - app/helpers/settings_template_helper.rb | 24 +- app/helpers/super_admin/orgs/merge_helper.rb | 50 +- app/helpers/template_helper.rb | 12 +- app/helpers/usage_helper.rb | 36 +- app/jobs/application_job.rb | 1 - app/mailers/user_mailer.rb | 72 +- app/models/annotation.rb | 2 - app/models/answer.rb | 14 +- app/models/api_client.rb | 10 +- app/models/application_record.rb | 2 - app/models/concerns/acts_as_sortable.rb | 12 +- app/models/concerns/date_rangeable.rb | 6 +- app/models/concerns/exportable_plan.rb | 53 +- app/models/concerns/identifiable.rb | 2 - app/models/concerns/json_link_validator.rb | 6 +- app/models/concerns/validation_messages.rb | 6 +- app/models/concerns/validation_values.rb | 2 - app/models/concerns/versionable_model.rb | 4 +- app/models/condition.rb | 2 - app/models/contributor.rb | 20 +- app/models/department.rb | 2 - app/models/exported_plan.rb | 40 +- app/models/guidance.rb | 29 +- app/models/guidance_group.rb | 4 +- app/models/identifier.rb | 20 +- app/models/identifier_scheme.rb | 8 +- app/models/language.rb | 8 +- app/models/mime_type.rb | 2 - app/models/note.rb | 2 - app/models/notification.rb | 6 +- app/models/org.rb | 54 +- app/models/perm.rb | 22 +- app/models/phase.rb | 10 +- app/models/plan.rb | 26 +- app/models/pref.rb | 2 - app/models/question.rb | 35 +- app/models/question_format.rb | 2 - app/models/question_option.rb | 2 - app/models/region.rb | 6 +- app/models/research_domain.rb | 6 +- app/models/research_output.rb | 2 - app/models/role.rb | 10 +- app/models/section.rb | 2 - app/models/section_sorter.rb | 2 - app/models/settings/template.rb | 38 +- app/models/stat.rb | 6 +- app/models/stat_created_plan.rb | 20 +- .../stat_created_plan/create_or_update.rb | 10 +- app/models/stat_exported_plan.rb | 4 - .../stat_exported_plan/create_or_update.rb | 6 - app/models/stat_joined_user.rb | 4 - .../stat_joined_user/create_or_update.rb | 6 - app/models/stat_shared_plan.rb | 4 - .../stat_shared_plan/create_or_update.rb | 6 - app/models/template.rb | 60 +- app/models/theme.rb | 8 +- app/models/token_permission_type.rb | 12 +- app/models/tracker.rb | 4 +- app/models/user.rb | 39 +- app/models/user/at_csv.rb | 18 +- app/policies/annotation_policy.rb | 11 +- app/policies/answer_policy.rb | 10 +- app/policies/api/v0/departments_policy.rb | 10 +- app/policies/api/v0/guidance_group_policy.rb | 12 +- app/policies/api/v0/guidance_policy.rb | 15 +- app/policies/api/v0/plans_policy.rb | 15 +- app/policies/api/v0/statistics_policy.rb | 12 +- app/policies/api/v0/template_policy.rb | 12 +- app/policies/api/v1/plans_policy.rb | 38 +- app/policies/api_client_policy.rb | 7 +- app/policies/application_policy.rb | 9 +- app/policies/department_policy.rb | 10 +- app/policies/guidance_group_policy.rb | 10 +- app/policies/guidance_policy.rb | 7 +- app/policies/identifier_policy.rb | 10 +- app/policies/note_policy.rb | 10 +- app/policies/notification_policy.rb | 7 +- app/policies/org_policy.rb | 7 +- app/policies/paginable/plan_policy.rb | 6 +- app/policies/phase_policy.rb | 7 +- app/policies/plan_policy.rb | 12 +- app/policies/public_page_policy.rb | 5 +- app/policies/question_option_policy.rb | 7 +- app/policies/question_policy.rb | 7 +- app/policies/role_policy.rb | 10 +- app/policies/section_policy.rb | 7 +- app/policies/settings/plan_policy.rb | 31 +- app/policies/settings/project_policy.rb | 37 +- app/policies/template_policy.rb | 7 +- app/policies/theme_policy.rb | 7 +- app/policies/token_permission_type_policy.rb | 7 +- app/policies/usage_policy.rb | 5 +- app/policies/user_policy.rb | 13 +- .../api/v1/contributor_presenter.rb | 13 +- app/presenters/api/v1/funding_presenter.rb | 21 +- app/presenters/api/v1/language_presenter.rb | 89 +- app/presenters/api/v1/org_presenter.rb | 13 +- app/presenters/api/v1/pagination_presenter.rb | 15 +- app/presenters/api/v1/plan_presenter.rb | 15 +- app/presenters/api/v1/template_presenter.rb | 7 +- app/presenters/contributor_presenter.rb | 33 +- app/presenters/guidance_presenter.rb | 19 +- app/presenters/identifier_presenter.rb | 12 +- app/presenters/org_selection_presenter.rb | 5 +- app/presenters/plan_presenter.rb | 5 +- .../super_admin/orgs/merge_presenter.rb | 27 +- app/scrubbers/table_free_scrubber.rb | 3 +- .../api/v1/auth/jwt/authentication_service.rb | 34 +- .../api/v1/auth/jwt/authorization_service.rb | 16 +- .../api/v1/auth/jwt/json_web_token.rb | 12 - .../api/v1/contextual_error_service.rb | 20 +- app/services/api/v1/conversion_service.rb | 18 +- .../api/v1/deserialization/contributor.rb | 14 +- .../api/v1/deserialization/dataset.rb | 10 - .../api/v1/deserialization/funding.rb | 10 - .../api/v1/deserialization/identifier.rb | 10 - app/services/api/v1/deserialization/org.rb | 14 +- app/services/api/v1/deserialization/plan.rb | 14 +- .../api/v1/deserialization_service.rb | 14 +- .../api/v1/json_validation_service.rb | 41 +- app/services/api/v1/persistence_service.rb | 8 - app/services/api/v1/validation_service.rb | 8 - app/services/application_service.rb | 6 +- app/services/external_apis/base_service.rb | 18 +- app/services/external_apis/doi_service.rb | 6 - .../external_apis/open_aire_service.rb | 22 +- app/services/external_apis/ror_service.rb | 58 +- app/services/locale_service.rb | 6 - .../org/create_created_plan_service.rb | 6 - .../org/create_exported_plan_service.rb | 6 - .../org/create_joined_user_service.rb | 6 - .../create_last_month_created_plan_service.rb | 6 - ...create_last_month_exported_plan_service.rb | 6 - .../create_last_month_joined_user_service.rb | 6 - .../create_last_month_shared_plan_service.rb | 6 - .../org/create_shared_plan_service.rb | 6 - app/services/org/monthly_usage_service.rb | 8 +- .../org/total_count_created_plan_service.rb | 10 +- .../org/total_count_joined_user_service.rb | 10 +- app/services/org/total_count_stat_service.rb | 6 - .../org_selection/hash_to_org_service.rb | 17 +- .../org_selection/org_to_hash_service.rb | 8 +- app/services/org_selection/search_service.rb | 16 +- .../template/upgrade_customization_service.rb | 10 +- app/validators/after_validator.rb | 10 +- .../answer_for_correct_template_validator.rb | 4 +- app/validators/email_validator.rb | 4 +- app/validators/org_links_validator.rb | 8 +- app/validators/template_links_validator.rb | 14 +- app/validators/url_validator.rb | 4 +- .../api/v0/statistics/plans.json.jbuilder | 2 +- .../api/v1/contributors/_show.json.jbuilder | 18 +- app/views/api/v1/datasets/_show.json.jbuilder | 12 +- app/views/api/v1/error.json.jbuilder | 2 +- app/views/api/v1/heartbeat.json.jbuilder | 2 +- app/views/api/v1/orgs/_show.json.jbuilder | 2 +- app/views/api/v1/plans/_funding.json.jbuilder | 8 +- app/views/api/v1/plans/_project.json.jbuilder | 4 +- app/views/api/v1/plans/_show.json.jbuilder | 16 +- app/views/api/v1/plans/index.json.jbuilder | 4 +- .../api/v1/templates/index.json.jbuilder | 6 +- app/views/plans/export.xml.builder | 20 +- config.ru | 4 +- config/application.rb | 10 +- config/boot.rb | 6 +- config/environment.rb | 2 +- config/environments/development.rb | 10 +- config/environments/production.rb | 8 +- config/environments/test.rb | 4 +- config/initializers/_dmproadmap.rb | 80 +- config/initializers/api_pagination.rb | 6 +- config/initializers/assets.rb | 4 +- config/initializers/contact_us.rb | 2 +- .../initializers/content_security_policy.rb | 4 +- config/initializers/devise.rb | 12 +- .../initializers/dmproadmap_schema_dumper.rb | 12 +- config/initializers/dragonfly.rb | 22 +- config/initializers/external_apis/doi.rb | 10 +- .../initializers/external_apis/open_aire.rb | 6 +- config/initializers/external_apis/ror.rb | 8 +- .../initializers/htmlto_word_xslt_helper.rb | 8 +- config/initializers/jbuilder_prettify.rb | 4 +- config/initializers/locale.rb | 2 +- config/initializers/recaptcha.rb | 4 +- config/initializers/rollbar.rb | 12 +- config/initializers/session_store.rb | 2 +- config/initializers/translation.rb | 58 +- config/locale/i18n_placeholders.rb | 10 +- config/puma.rb | 8 +- config/routes.rb | 240 ++-- lib/cleanup/deprecators.rb | 2 - lib/cleanup/deprecators/get_deprecator.rb | 17 +- .../deprecators/predicate_deprecator.rb | 15 +- lib/cleanup/deprecators/set_deprecator.rb | 17 +- lib/csvable.rb | 10 +- lib/custom_failure.rb | 2 - lib/data_cleanup.rb | 12 +- lib/data_cleanup/instance_check.rb | 12 +- lib/data_cleanup/model_check.rb | 18 +- lib/data_cleanup/reporting.rb | 4 - lib/data_cleanup/rules.rb | 7 +- lib/faker/language.rb | 14 +- .../data_cleanup_rule_generator.rb | 27 +- .../data_cleanup_rule/templates/base.rb | 6 - lib/global_helpers.rb | 2 - lib/org_date_rangeable.rb | 10 +- lib/sort_direction.rb | 4 +- lib/tasks/auto_annotate_models.rake | 76 +- lib/tasks/data_cleanup.rake | 209 ++-- lib/tasks/doc.rake | 28 +- lib/tasks/factory_bot.rake | 4 +- lib/tasks/gettext.rake | 2 +- lib/tasks/initialize_data.rake | 6 +- lib/tasks/migrate.rake | 266 ++-- lib/tasks/stat.rake | 57 +- lib/tasks/upgrade.rake | 1072 ++++++++--------- lib/tasks/utils/external_api.rake | 114 +- lib/tasks/utils/language.rake | 20 +- lib/tasks/utils/templates.rake | 24 +- lib/tasks/v3.rake | 26 +- lib/unique_random.rb | 4 +- spec/controllers/answers_controller_spec.rb | 76 +- .../concerns/org_selectable_spec.rb | 40 +- .../contributors_controller_spec.rb | 83 +- .../guidance_groups_controller_spec.rb | 50 +- spec/controllers/guidances_controller_spec.rb | 68 +- spec/controllers/notes_controller_spec.rb | 26 +- spec/controllers/orgs_controller_spec.rb | 76 +- .../registrations_controller_spec.rb | 17 +- .../super_admin/orgs_controller_spec.rb | 36 +- spec/controllers/usage_controller_spec.rb | 58 +- spec/csvable_spec.rb | 18 +- spec/factories/languages.rb | 6 +- spec/factories/orgs.rb | 2 +- spec/factories/perms.rb | 18 +- spec/factories/plans.rb | 9 +- spec/factories/prefs.rb | 1 - spec/factories/question_formats.rb | 35 +- spec/factories/stat_created_plan.rb | 2 +- spec/factories/templates.rb | 3 +- spec/factories/themes.rb | 2 +- spec/factories/users.rb | 2 +- .../annotations/annotations_editing_spec.rb | 38 +- spec/features/feedback_requests_spec.rb | 16 +- spec/features/locales_spec.rb | 43 +- spec/features/plans/exports_spec.rb | 81 +- spec/features/plans_spec.rb | 40 +- .../questions/checkbox_questions_spec.rb | 20 +- .../questions/dropdown_questions_spec.rb | 20 +- .../questions/radiobuttons_questions_spec.rb | 18 +- .../questions/textarea_questions_spec.rb | 20 +- .../questions/textfield_questions_spec.rb | 20 +- spec/features/registrations_spec.rb | 50 +- spec/features/sessions_spec.rb | 18 +- spec/features/super_admins/merge_org_spec.rb | 40 +- spec/features/super_admins/org_swaps_spec.rb | 24 +- spec/features/super_admins/orgs_spec.rb | 48 +- .../templates/templates_copying_spec.rb | 12 +- .../templates/templates_editings_spec.rb | 20 +- .../templates_upgrade_customisations_spec.rb | 72 +- spec/features/templates_spec.rb | 32 +- spec/helpers/identifier_helper_spec.rb | 23 +- spec/helpers/usage_helper_spec.rb | 82 +- spec/mixins/versionable_model.rb | 18 +- spec/models/annotation_spec.rb | 38 +- spec/models/answer_spec.rb | 163 +-- spec/models/api_client_spec.rb | 33 +- spec/models/concerns/date_rangeable_spec.rb | 46 +- spec/models/concerns/identifiable_spec.rb | 56 +- spec/models/condition_spec.rb | 2 +- spec/models/contributor_spec.rb | 58 +- spec/models/department_spec.rb | 15 +- spec/models/exported_plan_spec.rb | 22 +- spec/models/guidance_group_spec.rb | 104 +- spec/models/guidance_spec.rb | 121 +- spec/models/identifier_scheme_spec.rb | 51 +- spec/models/identifier_spec.rb | 114 +- spec/models/language_spec.rb | 106 +- spec/models/note_spec.rb | 12 +- spec/models/notification_spec.rb | 79 +- spec/models/org_spec.rb | 323 ++--- spec/models/perm_spec.rb | 300 ++--- spec/models/phase_spec.rb | 85 +- spec/models/plan_spec.rb | 608 ++++------ spec/models/pref_spec.rb | 20 +- spec/models/question_format_spec.rb | 56 +- spec/models/question_option_spec.rb | 42 +- spec/models/question_spec.rb | 154 +-- spec/models/region_spec.rb | 12 +- spec/models/research_domain_spec.rb | 6 +- spec/models/research_output_spec.rb | 27 +- spec/models/role_spec.rb | 33 +- spec/models/section_sorter_spec.rb | 48 +- spec/models/section_spec.rb | 43 +- spec/models/stat_created_plan_spec.rb | 62 +- spec/models/stat_joined_user_spec.rb | 26 +- spec/models/template_spec.rb | 685 ++++------- spec/models/theme_spec.rb | 43 +- spec/models/token_permission_type_spec.rb | 18 +- spec/models/tracker_spec.rb | 22 +- spec/models/user_spec.rb | 300 ++--- spec/policies/usage_policy_spec.rb | 21 +- .../api/v1/contributor_presenter_spec.rb | 24 +- .../api/v1/funding_presenter_spec.rb | 20 +- .../api/v1/language_presenter_spec.rb | 24 +- spec/presenters/api/v1/org_presenter_spec.rb | 16 +- .../api/v1/pagination_presenter_spec.rb | 92 +- spec/presenters/api/v1/plan_presenter_spec.rb | 16 +- .../api/v1/template_presenter_spec.rb | 10 +- spec/presenters/identifier_presenter_spec.rb | 36 +- .../org_selection_presenter_spec.rb | 32 +- spec/presenters/plan_presenter.rb | 16 +- .../super_admin/orgs/merge_presenter_spec.rb | 104 +- spec/rails_helper.rb | 16 +- .../api/v1/authentication_controller_spec.rb | 26 +- .../api/v1/base_api_controller_spec.rb | 47 +- spec/requests/api/v1/plans_controller.rb | 208 ++-- .../api/v1/templates_controller_spec.rb | 38 +- spec/requests/usage_downloads_spec.rb | 24 +- .../auth/jwt/authentication_service_spec.rb | 118 +- .../v1/auth/jwt/authorization_service_spec.rb | 38 +- .../api/v1/auth/jwt/json_web_token_spec.rb | 24 +- .../api/v1/contextual_error_service_spec.rb | 62 +- .../api/v1/conversion_service_spec.rb | 48 +- .../v1/deserialization/contributor_spec.rb | 64 +- .../api/v1/deserialization/funding_spec.rb | 20 +- .../api/v1/deserialization/identifier_spec.rb | 30 +- .../api/v1/deserialization/org_spec.rb | 38 +- .../api/v1/deserialization/plan_spec.rb | 97 +- .../api/v1/deserialization_service_spec.rb | 132 +- .../api/v1/json_validation_service_spec.rb | 132 +- .../api/v1/persistence_service_spec.rb | 77 +- .../api/v1/validation_service_spec.rb | 60 +- spec/services/application_service_spec.rb | 16 +- .../external_apis/base_service_spec.rb | 96 +- .../external_apis/ror_service_spec.rb | 304 +++-- spec/services/locale_service_spec.rb | 77 +- .../org/create_created_plan_service_spec.rb | 60 +- .../org/create_joined_user_service_spec.rb | 18 +- ...te_last_month_created_plan_service_spec.rb | 28 +- ...ate_last_month_joined_user_service_spec.rb | 10 +- .../total_count_created_plan_service_spec.rb | 12 +- .../total_count_joined_user_service_spec.rb | 12 +- .../org/total_count_stat_service_spec.rb | 20 +- .../org_selection/hash_to_org_service_spec.rb | 122 +- .../org_selection/org_to_hash_service_spec.rb | 16 +- .../org_selection/search_service_spec.rb | 218 ++-- .../upgrade_customization_service_spec.rb | 90 +- spec/spec_helper.rb | 16 +- spec/support/capybara.rb | 18 +- spec/support/database_cleaner.rb | 4 +- spec/support/factory_bot.rb | 1 - spec/support/faker.rb | 4 +- spec/support/helpers/api.rb | 6 +- spec/support/helpers/autocomplete_helper.rb | 10 +- spec/support/helpers/capybara_helper.rb | 2 - spec/support/helpers/identifier_helper.rb | 14 +- spec/support/helpers/links_helper.rb | 6 +- spec/support/helpers/roles_helper.rb | 6 +- spec/support/helpers/sessions_helper.rb | 10 +- spec/support/helpers/template_helper.rb | 2 - spec/support/helpers/tiny_mce_helper.rb | 4 +- spec/support/helpers/webmocks.rb | 8 +- spec/support/locales.rb | 4 +- spec/support/matchers/has_errors_matcher.rb | 8 +- spec/support/mocks/api_json_samples.rb | 224 ++-- spec/support/mocks/form_field_json_values.rb | 6 +- spec/support/shoulda.rb | 2 +- spec/support/wait_for_ajax.rb | 4 +- .../_standard_response.json_jbuilder_spec.rb | 74 +- .../contributors/_show.json.jbuilder_spec.rb | 46 +- .../v1/datasets/_show.json.jbuilder_spec.rb | 26 +- spec/views/api/v1/error.json.jbuilder_spec.rb | 22 +- .../identifiers/_show.json.jbuilder_spec.rb | 14 +- .../api/v1/orgs/_show.json.jbuilder_spec.rb | 24 +- .../api/v1/plans/_cost.json.jbuilder_spec.rb | 18 +- .../v1/plans/_funding.json.jbuilder_spec.rb | 28 +- .../v1/plans/_project.json.jbuilder_spec.rb | 20 +- .../api/v1/plans/_show.json.jbuilder_spec.rb | 58 +- .../v1/templates/index.json.jbuilder_spec.rb | 30 +- spec/views/api/v1/token.json.jbuilder_spec.rb | 26 +- 477 files changed, 8046 insertions(+), 10266 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 151c3c1def..ea80d9e6b2 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -104,7 +104,16 @@ Lint/UnmodifiedReduceAccumulator: # new in 1.1 # ----------- # - METRICS - # ----------- - +# briley Oct. 4th 2021 +# Default is 100 lines. Most of our controllers, models, etc. violate this +# Cop, so setting it to 300 since we do not have time to refactor everything +Metrics/ClassLength: + Max: 300 +# briley Oct. 4th 2021 +# Default is 10 lines which feels very restrictive but would also require us to do +# too much refactoring at this point. +Metrics/MethodLength: + Max: 20 # ------------ # - SECURITY - diff --git a/Gemfile b/Gemfile index 0ead3831fa..da765688da 100644 --- a/Gemfile +++ b/Gemfile @@ -1,39 +1,39 @@ # frozen_string_literal: true -source "https://rubygems.org" +source 'https://rubygems.org' -ruby ">= 2.6.3" +ruby '>= 2.6.3' # ===========# # CORE RAILS # # ===========# # Full-stack web application framework. (http://rubyonrails.org) -gem "rails", "~> 5.2" +gem 'rails', '~> 5.2' # TODO: Remove this once Rails addresses the issue with its dependency on mimemagic. Mimemagic had # an MIT license but was using some incompatible GPL license code. # Versions of mimemagic that were yanked: https://rubygems.org/gems/mimemagic/versions # Analysis of the issue: https://www.theregister.com/2021/03/25/ruby_rails_code/ -gem "mimemagic", "~> 0.3.7" +gem 'mimemagic', '~> 0.3.7' # Use sqlite3 as the database for Active Record # gem 'sqlite3', '~> 1.4' # Use Puma as the app server -gem "puma", group: :puma, require: false +gem 'puma', group: :puma, require: false # Use SCSS for stylesheets -gem "sass-rails" +gem 'sass-rails' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker -gem "webpacker" +gem 'webpacker' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks -gem "turbolinks" +gem 'turbolinks' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder -gem "jbuilder" +gem 'jbuilder' # Use Redis adapter to run Action Cable in production # gem "redis", "~> 4.0" @@ -44,7 +44,7 @@ gem "jbuilder" # gem "image_processing", "~> 1.2" # Reduces boot times through caching; required in config/boot.rb -gem "bootsnap", require: false +gem 'bootsnap', require: false # GEMS ADDED TO HELP HANDLE RAILS MIGRATION FROM 3.x to 4.2 # THESE GEMS HELP SUPPORT DEPRACATED FUNCTIONALITY AND WILL LOSE SUPPORT IN @@ -60,7 +60,7 @@ gem "bootsnap", require: false # Rollbar-gem is the SDK for Ruby apps and includes support for apps using # Rails, Sinatra, Rack, plain Ruby, and other frameworks. -gem "rollbar", group: :rollbar, require: false +gem 'rollbar', group: :rollbar, require: false # ======== # # DATABASE # @@ -68,14 +68,14 @@ gem "rollbar", group: :rollbar, require: false # A simple, fast Mysql library for Ruby, binding to libmysql # (http://github.com/brianmario/mysql2) -gem "mysql2", group: :mysql, require: false +gem 'mysql2', group: :mysql, require: false # Pg is the Ruby interface to the {PostgreSQL # RDBMS}[http://www.postgresql.org/](https://bitbucket.org/ged/ruby-pg) -gem "pg", group: :pgsql, require: false +gem 'pg', group: :pgsql, require: false # Bit fields for ActiveRecord (https://github.com/pboling/flag_shih_tzu) -gem "flag_shih_tzu" # , "~> 0.3.23" +gem 'flag_shih_tzu' # , "~> 0.3.23" # ======== # # SECURITY # @@ -83,35 +83,35 @@ gem "flag_shih_tzu" # , "~> 0.3.23" # Flexible authentication solution for Rails with Warden # (https://github.com/plataformatec/devise) -gem "devise" +gem 'devise' # An invitation strategy for Devise (https://github.com/scambra/devise_invitable) -gem "devise_invitable" +gem 'devise_invitable' # A generalized Rack framework for multiple-provider authentication. # (https://github.com/omniauth/omniauth) -gem "omniauth" +gem 'omniauth' # OmniAuth Shibboleth strategies for OmniAuth 1.x -gem "omniauth-shibboleth" +gem 'omniauth-shibboleth' # ORCID OAuth 2.0 Strategy for OmniAuth 1.0 # (https://github.com/datacite/omniauth-orcid) -gem "omniauth-orcid" +gem 'omniauth-orcid' # This gem provides a mitigation against CVE-2015-9284 (Cross-Site Request # Forgery on the request phase when using OmniAuth gem with a Ruby on Rails # application) by implementing a CSRF token verifier that directly uses # ActionController::RequestForgeryProtection code from Rails. # https://nvd.nist.gov/vuln/detail/CVE-2015-9284 -gem "omniauth-rails_csrf_protection" +gem 'omniauth-rails_csrf_protection' # A ruby implementation of the RFC 7519 OAuth JSON Web Token (JWT) standard. -gem "jwt" +gem 'jwt' # Gems for repository integration # OO authorization for Rails (https://github.com/elabs/pundit) -gem "pundit" +gem 'pundit' # ========== # # UI / VIEWS # @@ -120,22 +120,22 @@ gem "pundit" # Ruby gem to handle settings for ActiveRecord instances by storing them as # serialized Hash in a separate database table. Namespaces and defaults # included. (https://github.com/ledermann/rails-settings) -gem "ledermann-rails-settings" +gem 'ledermann-rails-settings' # Gem providing simple Contact Us functionality with a Rails 3+ Engine. # (https://github.com/jdutil/contact_us) -gem "contact_us" # COULD BE EASILY REPLACED WITH OUR OWN CODE +gem 'contact_us' # COULD BE EASILY REPLACED WITH OUR OWN CODE # Helpers for the reCAPTCHA API (http://github.com/ambethia/recaptcha) -gem "recaptcha" +gem 'recaptcha' # Ideal gem for handling attachments in Rails, Sinatra and Rack applications. # (http://github.com/markevans/dragonfly) -gem "dragonfly" +gem 'dragonfly' group :aws do # Amazon AWS S3 data store for use with the Dragonfly gem. - gem "dragonfly-s3_data_store" + gem 'dragonfly-s3_data_store' end # ========== # @@ -144,21 +144,21 @@ end # A pagination engine plugin for Rails 4+ and other modern frameworks # (https://github.com/kaminari/kaminari) -gem "kaminari" +gem 'kaminari' # Paginate in your headers, not in your response body. This follows the # proposed RFC-8288 standard for Web linking. -gem "api-pagination" +gem 'api-pagination' # =========== # # STYLESHEETS # # =========== # # Integrate SassC-Ruby into Rails. (https://github.com/sass/sassc-rails) -gem "sassc-rails" +gem 'sassc-rails' # Font-Awesome SASS (https://github.com/FortAwesome/font-awesome-sass) -gem "font-awesome-sass", "~> 5.13.0" +gem 'font-awesome-sass', '~> 5.13.0' # Use webpack to manage app-like JavaScript modules in Rails # (https://github.com/rails/webpacker) @@ -166,7 +166,7 @@ gem "font-awesome-sass", "~> 5.13.0" # Parse CSS and add vendor prefixes to CSS rules using values from the Can # I Use website. (https://github.com/ai/autoprefixer-rails) -gem "autoprefixer-rails" +gem 'autoprefixer-rails' # Minimal embedded v8 for Ruby (https://github.com/discourse/mini_racer) # gem "mini_racer" @@ -176,27 +176,27 @@ gem "autoprefixer-rails" # ========= # # Provides binaries for WKHTMLTOPDF project in an easily accessible package. -gem "wkhtmltopdf-binary" +gem 'wkhtmltopdf-binary' # PDF generator (from HTML) gem for Ruby on Rails # (https://github.com/mileszs/wicked_pdf) -gem "wicked_pdf" +gem 'wicked_pdf' # This simple gem allows you to create MS Word docx documents from simple # html documents. This makes it easy to create dynamic reports and forms # that can be downloaded by your users as simple MS Word docx files. # (http://github.com/karnov/htmltoword) -gem "htmltoword" +gem 'htmltoword' # Filename sanitization for Ruby. This is useful when you generate filenames for # downloads from user input -gem "zaru" +gem 'zaru' # ==================== # # INTERNATIONALIZATION # # ==================== # -gem "translation" +gem 'translation' # ========= # # UTILITIES # @@ -205,13 +205,13 @@ gem "translation" # Run any code in parallel Processes(> use all CPUs) or Threads(> speedup # blocking operations). Best suited for map-reduce or e.g. parallel downloads/uploads. # TODO: Replace use of this with ActiveJob where possible -gem "parallel" +gem 'parallel' # Makes http fun again! Wrapper to simplify the native Net::HTTP libraries -gem "httparty" +gem 'httparty' # Autoload dotenv in Rails. (https://github.com/bkeepers/dotenv) -gem "dotenv-rails" +gem 'dotenv-rails' # ================================= # # ENVIRONMENT SPECIFIC DEPENDENCIES # @@ -219,160 +219,159 @@ gem "dotenv-rails" group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console - gem "byebug", platforms: %i[mri mingw x64_mingw] + gem 'byebug', platforms: %i[mri mingw x64_mingw] end group :test do # RSpec for Rails (https://github.com/rspec/rspec-rails) - gem "rspec-rails" + gem 'rspec-rails' # factory_bot_rails provides integration between factory_bot and rails 3 # or newer (http://github.com/thoughtbot/factory_bot_rails) - gem "factory_bot_rails" + gem 'factory_bot_rails' # Easily generate fake data (https://github.com/stympy/faker) - gem "faker" + gem 'faker' # the instafailing RSpec progress bar formatter # (https://github.com/thekompanee/fuubar) - gem "fuubar" + gem 'fuubar' # Guard keeps an eye on your file modifications (http://guardgem.org) - gem "guard" + gem 'guard' # Guard gem for RSpec (https://github.com/guard/guard-rspec) - gem "guard-rspec" + gem 'guard-rspec' # Library for stubbing HTTP requests in Ruby. # (http://github.com/bblimke/webmock) - gem "webmock" + gem 'webmock' # Code coverage for Ruby 1.9+ with a powerful configuration library and # automatic merging of coverage across test suites # (http://github.com/colszowka/simplecov) - gem "simplecov", require: false + gem 'simplecov', require: false # Strategies for cleaning databases. Can be used to ensure a clean state # for testing. (http://github.com/DatabaseCleaner/database_cleaner) - gem "database_cleaner", require: false + gem 'database_cleaner', require: false # Making tests easy on the fingers and eyes # (https://github.com/thoughtbot/shoulda) - gem "shoulda", require: false + gem 'shoulda', require: false # Mocking and stubbing library (http://gofreerange.com/mocha/docs) - gem "mocha", require: false + gem 'mocha', require: false # Adds support for Capybara system testing and selenium driver - gem "capybara" - gem "selenium-webdriver" + gem 'capybara' + gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers - gem "webdrivers" + gem 'webdrivers' # Automatically create snapshots when Cucumber steps fail with Capybara # and Rails (http://github.com/mattheworiordan/capybara-screenshot) - gem "capybara-screenshot" + gem 'capybara-screenshot' # Browser integration tests are expensive. We can mock external requests # in our tests, but once a browser is involved, we lose control. - gem "capybara-webmock" + gem 'capybara-webmock' # RSpec::CollectionMatchers lets you express expected outcomes on # collections of an object in an example. - gem "rspec-collection_matchers" + gem 'rspec-collection_matchers' # A set of RSpec matchers for testing Pundit authorisation policies. - gem "pundit-matchers" + gem 'pundit-matchers' # This gem brings back assigns to your controller tests as well as assert_template # to both controller and integration tests. - gem "rails-controller-testing" + gem 'rails-controller-testing' end group :ci, :development do # Security vulnerability scanner for Ruby on Rails. # (http://brakemanscanner.org) - gem "brakeman" + gem 'brakeman' # Helper gem to require bundler-audit # (http://github.com/stewartmckee/bundle-audit) - gem "bundle-audit" + gem 'bundle-audit' # RuboCop is a Ruby code style checking and code formatting tool. It aims to enforce # the community-driven Ruby Style Guide. - gem "rubocop" + gem 'rubocop' # RuboCop rules for detecting and autocorrecting undecorated strings for i18n # (gettext and rails-i18n) - gem "rubocop-i18n" + gem 'rubocop-i18n' # A collection of RuboCop cops to check for performance optimizations in Ruby code. - gem "rubocop-performance" + gem 'rubocop-performance' # Automatic Rails code style checking tool. A RuboCop extension focused on enforcing # Rails best practices and coding conventions. - gem "rubocop-rails" + gem 'rubocop-rails' # A RuboCop plugin for Rake tasks - gem "rubocop-rake" + gem 'rubocop-rake' # Code style checking for RSpec files. A plugin for the RuboCop code style enforcing # & linting tool. - gem "rubocop-rspec" + gem 'rubocop-rspec' # Thread-safety checks via static analysis. A plugin for the RuboCop code style # enforcing & linting tool. - gem "rubocop-thread_safety" - + gem 'rubocop-thread_safety' end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. - gem "listen" - gem "web-console" + gem 'listen' + gem 'web-console' # Spring speeds up development by keeping your application running in the background. # Read more: https://github.com/rails/spring - gem "spring" - gem "spring-watcher-listen" + gem 'spring' + gem 'spring-watcher-listen' # Simple Progress Bar for output to a terminal # (http://github.com/paul/progress_bar) - gem "progress_bar", require: false + gem 'progress_bar', require: false # A collection of text algorithms (http://github.com/threedaymonk/text) - gem "text", require: false + gem 'text', require: false # Better error page for Rails and other Rack apps # (https://github.com/charliesome/better_errors) - gem "better_errors" + gem 'better_errors' # Retrieve the binding of a method's caller. Can also retrieve bindings # even further up the stack. (http://github.com/banister/binding_of_caller) - gem "binding_of_caller" + gem 'binding_of_caller' # rspec command for spring # (https://github.com/jonleighton/spring-commands-rspec) - gem "spring-commands-rspec" + gem 'spring-commands-rspec' # Profiles loading speed for rack applications. (http://miniprofiler.com) - gem "rack-mini-profiler" + gem 'rack-mini-profiler' # Annotates Rails Models, routes, fixtures, and others based on the # database schema. (http://github.com/ctran/annotate_models) - gem "annotate" + gem 'annotate' # Add comments to your Gemfile with each dependency's description. # (https://github.com/ivantsepp/annotate_gem) - gem "annotate_gem" + gem 'annotate_gem' # help to kill N+1 queries and unused eager loading. # (https://github.com/flyerhzm/bullet) - gem "bullet" + gem 'bullet' # Documentation tool for consistent and usable documentation in Ruby. # (http://yardoc.org) - gem "yard" + gem 'yard' # TomDoc for YARD (http://rubyworks.github.com/yard-tomdoc) - gem "yard-tomdoc" + gem 'yard-tomdoc' end diff --git a/Rakefile b/Rakefile index 700a8a33cf..42f9525d64 100755 --- a/Rakefile +++ b/Rakefile @@ -10,7 +10,7 @@ # task default: :test -require_relative "config/application" +require_relative 'config/application' DMPRoadmap::Application.load_tasks diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb index fa6ee697da..9aec230539 100644 --- a/app/channels/application_cable/channel.rb +++ b/app/channels/application_cable/channel.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true module ApplicationCable - class Channel < ActionCable::Channel::Base - end - end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index b08f85080a..8d6c2a1bf4 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true module ApplicationCable - class Connection < ActionCable::Connection::Base - end - end diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb index 48980290bf..9e089bd5d4 100644 --- a/app/controllers/answers_controller.rb +++ b/app/controllers/answers_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true +# Controller that handles Answers to DMP questions class AnswersController < ApplicationController - respond_to :html include ConditionsHelper @@ -12,6 +12,7 @@ class AnswersController < ApplicationController # `remote: true` in the
tag and just send back the ERB. # Consider using ActionCable for the progress bar(s) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def create_or_update p_params = permitted_params @@ -21,21 +22,17 @@ def create_or_update unless p.question_exists?(p_params[:question_id]) # rubocop:disable Layout/LineLength render(status: :not_found, json: { - msg: _("There is no question with id %{question_id} associated to plan id %{plan_id} for which to create or update an answer") % { - question_id: p_params[:question_id], - plan_id: p_params[:plan_id] - } + msg: format(_('There is no question with id %s associated to plan id %s for which to create or update an answer'), question_id: p_params[:question_id], plan_id: p_params[:plan_id]) }) # rubocop:enable Layout/LineLength return end rescue ActiveRecord::RecordNotFound + # rubocop:disable Layout/LineLength render(status: :not_found, json: { - msg: _("There is no plan with id %{id} for which to create or update an answer") % { - id: p_params[:plan_id] - } + msg: format(_('There is no plan with id %s for which to create or update an answer'), id: p_params[:plan_id]) }) - + # rubocop:enable Layout/LineLength return end q = Question.find(p_params[:question_id]) @@ -127,19 +124,19 @@ def create_or_update send_webhooks(current_user, @answer) render json: { - "qn_data": qn_data, - "section_data": section_data, - "question" => { - "id" => @question.id, - "answer_lock_version" => @answer.lock_version, - "locking" => if @stale_answer - render_to_string(partial: "answers/locking", locals: { + qn_data: qn_data, + section_data: section_data, + 'question' => { + 'id' => @question.id, + 'answer_lock_version' => @answer.lock_version, + 'locking' => if @stale_answer + render_to_string(partial: 'answers/locking', locals: { question: @question, answer: @stale_answer, user: @answer.user }, formats: [:html]) end, - "form" => render_to_string(partial: "answers/new_edit", locals: { + 'form' => render_to_string(partial: 'answers/new_edit', locals: { template: template, question: @question, answer: @answer, @@ -147,13 +144,13 @@ def create_or_update locking: false, base_template_org: template.base_org }, formats: [:html]), - "answer_status" => render_to_string(partial: "answers/status", locals: { + 'answer_status' => render_to_string(partial: 'answers/status', locals: { answer: @answer }, formats: [:html]) }, - "plan" => { - "id" => @plan.id, - "progress" => render_to_string(partial: "plans/progress", locals: { + 'plan' => { + 'id' => @plan.id, + 'progress' => render_to_string(partial: 'plans/progress', locals: { plan: @plan, current_phase: @section.phase }, formats: [:html]) @@ -164,10 +161,11 @@ def create_or_update # rubocop:enable Style/GuardClause end # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - # rubocop:enable + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity private + # rubocop:disable Metrics/AbcSize def permitted_params permitted = params.require(:answer) .permit(:id, :text, :plan_id, :user_id, :question_id, @@ -184,11 +182,11 @@ def permitted_params permitted[:question_option_ids] = [] if params[:answer][:question_option_ids].nil? permitted end + # rubocop:enable Metrics/AbcSize def check_answered(section, q_array, all_answers) n_qs = section.questions.select { |question| q_array.include?(question.id) }.length n_ans = all_answers.select { |ans| q_array.include?(ans.question.id) and ans.answered? }.length [n_qs, n_ans] end - end diff --git a/app/controllers/api/v0/base_controller.rb b/app/controllers/api/v0/base_controller.rb index f90f9c7320..c955adfdab 100644 --- a/app/controllers/api/v0/base_controller.rb +++ b/app/controllers/api/v0/base_controller.rb @@ -1,127 +1,130 @@ # frozen_string_literal: true -class Api::V0::BaseController < ApplicationController - - protect_from_forgery with: :null_session - before_action :define_resource, only: %i[destroy show update] - respond_to :json - - # POST /api/{plural_resource_name} - def create - define_resource(resource_class.new(resource_params)) +module Api + module V0 + # Generic controller for API V0 + class BaseController < ApplicationController + protect_from_forgery with: :null_session + before_action :define_resource, only: %i[destroy show update] + respond_to :json + + # POST /api/{plural_resource_name} + def create + define_resource(resource_class.new(resource_params)) + + if retrieve_resource.save + render :show, status: :created + else + render json: retrieve_resource.errors, status: :unprocessable_entity + end + end - if retrieve_resource.save - render :show, status: :created - else - render json: retrieve_resource.errors, status: :unprocessable_entity - end - end + # DELETE /api/{plural_resource_name}/1 + def destroy + retrieve_resource.destroy + head :no_content + end - # DELETE /api/{plural_resource_name}/1 - def destroy - retrieve_resource.destroy - head :no_content - end + # GET /api/{plural_resource_name} + def index + plural_resource_name = "@#{resource_name.pluralize}" + resources = resource_class.where(query_params) + .page(page_params[:page]) + .per(page_params[:page_size]) - # GET /api/{plural_resource_name} - def index - plural_resource_name = "@#{resource_name.pluralize}" - resources = resource_class.where(query_params) - .page(page_params[:page]) - .per(page_params[:page_size]) + instance_variable_set(plural_resource_name, resources) + respond_with instance_variable_get(plural_resource_name) + end - instance_variable_set(plural_resource_name, resources) - respond_with instance_variable_get(plural_resource_name) - end + # GET /api/{plural_resource_name}/1 + def show + respond_with retrieve_resource + end - # GET /api/{plural_resource_name}/1 - def show - respond_with retrieve_resource - end + # PATCH/PUT /api/{plural_resource_name}/1 + def update + if retrieve_resource.update(resource_params) + render :show + else + render json: retrieve_resource.errors, status: :unprocessable_entity + end + end - # PATCH/PUT /api/{plural_resource_name}/1 - def update - if retrieve_resource.update(resource_params) - render :show - else - render json: retrieve_resource.errors, status: :unprocessable_entity - end - end + private - private + # The resource from the created instance variable + # + # Returns Object + def retrieve_resource + instance_variable_get("@#{resource_name}") + end - # The resource from the created instance variable - # - # Returns Object - def retrieve_resource - instance_variable_get("@#{resource_name}") - end + # The allowed parameters for searching. Override this method in each API + # controller to permit additional parameters to search on + # + # Returns Hash + def query_params + {} + end - # The allowed parameters for searching. Override this method in each API - # controller to permit additional parameters to search on - # - # Returns Hash - def query_params - {} - end + # The allowed parameters for pagination + # + # Returns Hash + def page_params + params.permit(:page, :page_size) + end - # The allowed parameters for pagination - # - # Returns Hash - def page_params - params.permit(:page, :page_size) - end + # The resource class based on the controller + # + # Returns Object + def resource_class + @resource_class ||= resource_name.classify.constantize + end - # The resource class based on the controller - # - # Returns Object - def resource_class - @resource_class ||= resource_name.classify.constantize - end + # The singular name for the resource class based on the controller + # + # Returns String + def resource_name + @resource_name ||= controller_name.singularize + end - # The singular name for the resource class based on the controller - # - # Returns String - def resource_name - @resource_name ||= controller_name.singularize - end + # Only allow a trusted parameter "white list" through. + # If a single resource is loaded for #create or #update, + # then the controller for the resource must implement + # the method "#{resource_name}_params" to limit permitted + # parameters for the individual model. + def resource_params + @resource_params ||= send("#{resource_name}_params") + end - # Only allow a trusted parameter "white list" through. - # If a single resource is loaded for #create or #update, - # then the controller for the resource must implement - # the method "#{resource_name}_params" to limit permitted - # parameters for the individual model. - def resource_params - @resource_params ||= send("#{resource_name}_params") - end + # Use callbacks to share common setup or constraints between actions. + def define_resource(resource = nil) + resource ||= resource_class.find(params[:id]) + instance_variable_set("@#{resource_name}", resource) + end - # Use callbacks to share common setup or constraints between actions. - def define_resource(resource = nil) - resource ||= resource_class.find(params[:id]) - instance_variable_set("@#{resource_name}", resource) - end + def authenticate + authenticate_token || render_bad_credentials + end - def authenticate - authenticate_token || render_bad_credentials - end + def authenticate_token + authenticate_with_http_token do |token, _options| + # reject the empty string as it is our base empty token + if token == '' + false + else + @token = token + @user = User.find_by(api_token: token) + # if no user found, return false, otherwise true + !@user.nil? && @user.can_use_api? + end + end + end - def authenticate_token - authenticate_with_http_token do |token, _options| - # reject the empty string as it is our base empty token - if token != "" - @token = token - @user = User.find_by(api_token: token) - # if no user found, return false, otherwise true - !@user.nil? && @user.can_use_api? - else - false + def render_bad_credentials + headers['WWW-Authenticate'] = 'Token realm=""' + render json: _('Bad Credentials'), status: 401 end end end - - def render_bad_credentials - headers["WWW-Authenticate"] = "Token realm=\"\"" - render json: _("Bad Credentials"), status: 401 - end - end diff --git a/app/controllers/api/v0/departments_controller.rb b/app/controllers/api/v0/departments_controller.rb index 5bd31d6f18..83e483cce7 100644 --- a/app/controllers/api/v0/departments_controller.rb +++ b/app/controllers/api/v0/departments_controller.rb @@ -1,80 +1,79 @@ # frozen_string_literal: true -class Api::V0::DepartmentsController < Api::V0::BaseController - - before_action :authenticate - - ## - # Create a new department based on the information passed in JSON to the API - def create - raise Pundit::NotAuthorizedError unless Api::V0::DepartmentsPolicy.new(@user, nil).index? +module Api + module V0 + # Handles CRUD operations for Departments in API V0 + class DepartmentsController < Api::V0::BaseController + before_action :authenticate + + ## + # Create a new department based on the information passed in JSON to the API + def create + raise Pundit::NotAuthorizedError unless Api::V0::DepartmentsPolicy.new(@user, nil).index? + + @department = Department.new(org: @user.org, + code: params[:code], + name: params[:name]) + if @department.save + redirect_to api_v0_departments_path + else + # the department did not save + headers['WWW-Authenticate'] = 'Token realm=""' + render json: _('Departments code and name must be unique'), status: 400 + end + end - @department = Department.new(org: @user.org, - code: params[:code], - name: params[:name]) - if @department.save - redirect_to api_v0_departments_path - else - # the department did not save - headers["WWW-Authenticate"] = "Token realm=\"\"" - render json: _("Departments code and name must be unique"), status: 400 - end - end + ## + # Lists the departments for the API user's organisation + def index + raise Pundit::NotAuthorizedError unless Api::V0::DepartmentsPolicy.new(@user, nil).index? - ## - # Lists the departments for the API user's organisation - def index - raise Pundit::NotAuthorizedError unless Api::V0::DepartmentsPolicy.new(@user, nil).index? + @departments = @user.org.departments + end - @departments = @user.org.departments - end + ## + # List the users for each department on the organisation + def users + raise Pundit::NotAuthorizedError unless Api::V0::DepartmentsPolicy.new(@user, nil).users? - ## - # List the users for each department on the organisation - def users - raise Pundit::NotAuthorizedError unless Api::V0::DepartmentsPolicy.new(@user, nil).users? + @users = @user.org.users.includes(:department) + end - @users = @user.org.users.includes(:department) - end + ## + # Assign the list of users to the passed department id + def assign_users + @department = Department.find(params[:id]) - ## - # Assign the list of users to the passed department id - def assign_users - @department = Department.find(params[:id]) + raise Pundit::NotAuthorizedError unless Api::V0::DepartmentsPolicy.new(@user, @department).assign_users? - unless Api::V0::DepartmentsPolicy.new(@user, @department).assign_users? - raise Pundit::NotAuthorizedError - end + assign_users_to(@department.id) + redirect_to users_api_v0_departments_path + end - assign_users_to(@department.id) - redirect_to users_api_v0_departments_path - end + ## + # Remove departments from the list of users + def unassign_users + raise Pudndit::NotAuthorizedError unless Api::V0::DepartmentsPolicy.new(@user, @department).assign_users? - ## - # Remove departments from the list of users - def unassign_users - unless Api::V0::DepartmentsPolicy.new(@user, @department).assign_users? - raise Pudndit::NotAuthorizedError - end + assign_users_to(nil) + redirect_to users_api_v0_departments_path + end - assign_users_to(nil) - redirect_to users_api_v0_departments_path - end + private - private + def assign_users_to(department_id) + params[:users].each do |email| + reassign = User.find_by(email: email) + # Currently the validation is that the user's org matches the API user's + # Not sure if this is possible to capture in pundit + unless @user.present? && @user.org == reassign&.org + raise Pundit::NotAuthorizedError, _("user #{email} was not found on your organisation") + end - def assign_users_to(department_id) - params[:users].each do |email| - reassign = User.find_by(email: email) - # Currently the validation is that the user's org matches the API user's - # Not sure if this is possible to capture in pundit - unless @user.present? && @user.org == reassign&.org - raise Pundit::NotAuthorizedError, _("user #{email} was not found on your organisation") + reassign.department_id = department_id + reassign.save! + end end - - reassign.department_id = department_id - reassign.save! end end - end diff --git a/app/controllers/api/v0/guidance_groups_controller.rb b/app/controllers/api/v0/guidance_groups_controller.rb index 17beae33d4..7c828f1f69 100644 --- a/app/controllers/api/v0/guidance_groups_controller.rb +++ b/app/controllers/api/v0/guidance_groups_controller.rb @@ -1,26 +1,27 @@ # frozen_string_literal: true -class Api::V0::GuidanceGroupsController < Api::V0::BaseController +module Api + module V0 + # Handles GuidanceGroup queries for API V0 + class GuidanceGroupsController < Api::V0::BaseController + before_action :authenticate - before_action :authenticate + def index + raise Pundit::NotAuthorizedError unless Api::V0::GuidanceGroupPolicy.new(@user, :guidance_group).index? - def index - unless Api::V0::GuidanceGroupPolicy.new(@user, :guidance_group).index? - raise Pundit::NotAuthorizedError - end - - @all_viewable_groups = GuidanceGroup.all_viewable(@user) - respond_with @all_viewable_groups - end + @all_viewable_groups = GuidanceGroup.all_viewable(@user) + respond_with @all_viewable_groups + end - def pundit_user - @user - end + def pundit_user + @user + end - private + private - def query_params - params.permit(:id) + def query_params + params.permit(:id) + end + end end - end diff --git a/app/controllers/api/v0/plans_controller.rb b/app/controllers/api/v0/plans_controller.rb index 5e30069bda..8fa848bffd 100644 --- a/app/controllers/api/v0/plans_controller.rb +++ b/app/controllers/api/v0/plans_controller.rb @@ -1,123 +1,123 @@ # frozen_string_literal: true -class Api::V0::PlansController < Api::V0::BaseController - - include Paginable - - before_action :authenticate - - ## - # Creates a new plan based on the information passed in JSON to the API - # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - def create - @template = Template.live(params[:template_id]) - raise Pundit::NotAuthorizedError unless Api::V0::PlansPolicy.new(@user, @template).create? - - plan_user = User.find_by(email: params[:plan][:email]) - # ensure user exists - if plan_user.blank? - User.invite!({ email: params[:plan][:email] }, @user) - plan_user = User.find_by(email: params[:plan][:email]) - plan_user.org = @user.org - plan_user.save - end - # ensure user's organisation is the same as api user's - unless plan_user.org == @user.org - raise Pundit::NotAuthorizedError, _("user must be in your organisation") - end - - # initialize the plan - @plan = Plan.new - - # Attach the user as the PI and Data Contact - @plan.contributors << Contributor.new( - name: [plan_user.firstname, plan_user.surname].join(" "), - email: plan_user.email, - investigation: true, - data_curation: true - ) - - # set funder name to template's org, or original template's org - @plan.funder_id = if @template.customization_of.nil? - @template.org.id - else - Template.where( - family_id: @template.customization_of - ).first.org.id - end - @plan.template = @template - @plan.title = params[:plan][:title] - if @plan.save - @plan.assign_creator(plan_user) - respond_with @plan - else - # the plan did not save - headers["WWW-Authenticate"] = "Token realm=\"\"" - render json: _("Bad Parameters"), status: 400 +module Api + module V0 + # Primary controller for API V0 that handles CRUD operations for Plans + class PlansController < Api::V0::BaseController + include Paginable + + before_action :authenticate + + ## + # Creates a new plan based on the information passed in JSON to the API + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + def create + @template = Template.live(params[:template_id]) + raise Pundit::NotAuthorizedError unless Api::V0::PlansPolicy.new(@user, @template).create? + + plan_user = User.find_by(email: params[:plan][:email]) + # ensure user exists + if plan_user.blank? + User.invite!({ email: params[:plan][:email] }, @user) + plan_user = User.find_by(email: params[:plan][:email]) + plan_user.org = @user.org + plan_user.save + end + # ensure user's organisation is the same as api user's + raise Pundit::NotAuthorizedError, _('user must be in your organisation') unless plan_user.org == @user.org + + # initialize the plan + @plan = Plan.new + + # Attach the user as the PI and Data Contact + @plan.contributors << Contributor.new( + name: [plan_user.firstname, plan_user.surname].join(' '), + email: plan_user.email, + investigation: true, + data_curation: true + ) + + # set funder name to template's org, or original template's org + @plan.funder_id = if @template.customization_of.nil? + @template.org.id + else + Template.where( + family_id: @template.customization_of + ).first.org.id + end + @plan.template = @template + @plan.title = params[:plan][:title] + if @plan.save + @plan.assign_creator(plan_user) + respond_with @plan + else + # the plan did not save + headers['WWW-Authenticate'] = 'Token realm=""' + render json: _('Bad Parameters'), status: 400 + end + end + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength + + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + def index + raise Pundit::NotAuthorizedError unless Api::V0::PlansPolicy.new(@user, nil).index? + + if params[:per_page].present? + max_pages = Rails.configuration.x.application.api_max_page_size + params[:per_page] = max_pages if params[:per_page].to_i > max_pages + end + + # Get all the Org Admin plans + org_admin_plans = @user.org.org_admin_plans + @plans = org_admin_plans.includes([{ roles: :user }, { answers: :question_options }, + template: [{ phases: { + sections: { questions: %i[question_format themes] } + } }, :org]]) + + # Filter on list of users + user_ids = extract_param_list(params, 'user') + @plans = @plans.where(roles: { user_id: user_ids, access: Role.bit_values(:editor) }) if user_ids.present? + # filter on dates + if params['created_after'].present? || params['created_before'].present? + @plans = @plans.where(created_at: dates_to_range(params, 'created_after', 'created_before')) + end + if params['updated_after'].present? || params['updated_before'].present? + @plans = @plans.where(updated_at: dates_to_range(params, 'updated_after', 'updated_before')) + end + if params['remove_tests'].present? && params['remove_tests'].downcase == 'true' + @plans = @plans.where.not(visibility: Plan.visibilities[:is_test]) + end + # filter on funder (dmptemplate_id) + template_ids = extract_param_list(params, 'template') + @plans = @plans.where(templates: { family_id: template_ids }) if template_ids.present? + # filter on id(s) + plan_ids = extract_param_list(params, 'plan') + @plans = @plans.where(id: plan_ids) if plan_ids.present? + # apply pagination after filtering + @args = { per_page: params[:per_page], page: params[:page] } + @plans = refine_query(@plans) + respond_with @plans + end + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + + private + + def extract_param_list(params, attribute) + list = params.fetch("#{attribute}[]", []) + val = params.fetch(attribute, []) + list << val if val.present? + list + end + + # takes in the params hash and converts to a date-range + def dates_to_range(hash, start, stop) + today = Date.today + start_date = Date.parse(hash.fetch(start, today.prev_month.to_date.to_s)) + end_date = Date.parse(hash.fetch(stop, today.to_date.to_s)) + 1.day + start_date..end_date + end end end - # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - - # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - def index - raise Pundit::NotAuthorizedError unless Api::V0::PlansPolicy.new(@user, nil).index? - - if params[:per_page].present? - max_pages = Rails.configuration.x.application.api_max_page_size - params[:per_page] = max_pages if params[:per_page].to_i > max_pages - end - - # Get all the Org Admin plans - org_admin_plans = @user.org.org_admin_plans - @plans = org_admin_plans.includes([{ roles: :user }, { answers: :question_options }, - template: [{ phases: { - sections: { questions: %i[question_format themes] } - } }, :org]]) - - # Filter on list of users - user_ids = extract_param_list(params, "user") - if user_ids.present? - @plans = @plans.where(roles: { user_id: user_ids, access: Role.bit_values(:editor) }) - end - # filter on dates - if params["created_after"].present? || params["created_before"].present? - @plans = @plans.where(created_at: dates_to_range(params, "created_after", "created_before")) - end - if params["updated_after"].present? || params["updated_before"].present? - @plans = @plans.where(updated_at: dates_to_range(params, "updated_after", "updated_before")) - end - if params["remove_tests"].present? && params["remove_tests"].downcase == "true" - @plans = @plans.where.not(visibility: Plan.visibilities[:is_test]) - end - # filter on funder (dmptemplate_id) - template_ids = extract_param_list(params, "template") - @plans = @plans.where(templates: { family_id: template_ids }) if template_ids.present? - # filter on id(s) - plan_ids = extract_param_list(params, "plan") - @plans = @plans.where(id: plan_ids) if plan_ids.present? - # apply pagination after filtering - @args = { per_page: params[:per_page], page: params[:page] } - @plans = refine_query(@plans) - respond_with @plans - end - # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - # rubocop:enable - - private - - def extract_param_list(params, attribute) - list = params.fetch(attribute + "[]", []) - val = params.fetch(attribute, []) - list << val if val.present? - list - end - - # takes in the params hash and converts to a date-range - def dates_to_range(hash, start, stop) - today = Date.today - start_date = Date.parse(hash.fetch(start, today.prev_month.to_date.to_s)) - end_date = Date.parse(hash.fetch(stop, today.to_date.to_s)) + 1.day - start_date..end_date - end - end diff --git a/app/controllers/api/v0/statistics_controller.rb b/app/controllers/api/v0/statistics_controller.rb index b74f1a241d..2af50dfcb2 100644 --- a/app/controllers/api/v0/statistics_controller.rb +++ b/app/controllers/api/v0/statistics_controller.rb @@ -1,244 +1,243 @@ # frozen_string_literal: true -class Api::V0::StatisticsController < Api::V0::BaseController - - before_action :authenticate - - # GET /api/v0/statistics/users_joined?start_date=&end_date=&org_id= - # - # Returns the number of users joined for the user's org. - # If start_date is passed, only counts those with created_at is >= than start_date - # If end_date is passed, only counts those with created_at is <= than end_date are - # If org_id is passed and user has super_admin privileges that counter is performed - # against org_id param instead of user's org - - # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - def users_joined - unless Api::V0::StatisticsPolicy.new(@user, :statistics).users_joined? - raise Pundit::NotAuthorizedError - end - - scoped = if @user.can_super_admin? && params[:org_id].present? - User.unscoped.where(org_id: params[:org_id]) - else - User.unscoped.where(org_id: @user.org_id) - end - - if params[:range_dates].present? - r = {} - params[:range_dates].each_pair do |k, v| - r[k] = scoped.where(created_at: dates_to_range(v)).count - end - - # Reverse hash r, so dates in ascending order - r = Hash[r.to_a.reverse] - - respond_to do |format| - format.json { render(json: r.to_json) } - format.csv do - send_data(CSV.generate do |csv| - csv << [_("Month"), _("No. Users joined")] - total = 0 - r.each_pair do |k, v| - csv << [k, v] - total += v +module Api + module V0 + # Provides statistical info for API V0 + class StatisticsController < Api::V0::BaseController + before_action :authenticate + + # GET /api/v0/statistics/users_joined?start_date=&end_date=&org_id= + # + # Returns the number of users joined for the user's org. + # If start_date is passed, only counts those with created_at is >= than start_date + # If end_date is passed, only counts those with created_at is <= than end_date are + # If org_id is passed and user has super_admin privileges that counter is performed + # against org_id param instead of user's org + + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + def users_joined + raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).users_joined? + + scoped = if @user.can_super_admin? && params[:org_id].present? + User.unscoped.where(org_id: params[:org_id]) + else + User.unscoped.where(org_id: @user.org_id) + end + + if params[:range_dates].present? + r = {} + params[:range_dates].each_pair do |k, v| + r[k] = scoped.where(created_at: dates_to_range(v)).count + end + + # Reverse hash r, so dates in ascending order + r = r.to_a.reverse.to_h + + respond_to do |format| + format.json { render(json: r.to_json) } + format.csv do + send_data(CSV.generate do |csv| + csv << [_('Month'), _('No. Users joined')] + total = 0 + r.each_pair do |k, v| + csv << [k, v] + total += v + end + csv << [_('Total'), total] + end, filename: "#{_('users_joined')}.csv") end - csv << [_("Total"), total] - end, filename: "#{_('users_joined')}.csv") + end + else + if params['start_date'].present? || params['end_date'].present? + scoped = scoped.where(created_at: dates_to_range(params)) + end + @users_count = scoped.count + respond_with @users_count end end - else - if params["start_date"].present? || params["end_date"].present? - scoped = scoped.where(created_at: dates_to_range(params)) - end - @users_count = scoped.count - respond_with @users_count - end - end - # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - # rubocop:enable - - # GET - # Returns the number of completed plans within the user's org for the data - # start_date and end_date specified - # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - def completed_plans - unless Api::V0::StatisticsPolicy.new(@user, :statistics).completed_plans? - raise Pundit::NotAuthorizedError - end - - scoped = if @user.can_super_admin? && params[:org_id].present? - Org.find(params[:org_id]).plans.where(complete: true) - else - @user.org.plans.where(complete: true) - end - - if params[:range_dates].present? - r = {} - params[:range_dates].each_pair do |k, v| - r[k] = scoped.where(created_at: dates_to_range(v)).count - end - - # Reverse hash r, so dates in ascending order - r = Hash[r.to_a.reverse] - - respond_to do |format| - format.json { render(json: r.to_json) } - format.csv do - send_data(CSV.generate do |csv| - csv << [_("Month"), _("No. Completed Plans")] - total = 0 - r.each_pair do |k, v| - csv << [k, v] - total += v + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + + # GET + # Returns the number of completed plans within the user's org for the data + # start_date and end_date specified + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + def completed_plans + raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).completed_plans? + + scoped = if @user.can_super_admin? && params[:org_id].present? + Org.find(params[:org_id]).plans.where(complete: true) + else + @user.org.plans.where(complete: true) + end + + if params[:range_dates].present? + r = {} + params[:range_dates].each_pair do |k, v| + r[k] = scoped.where(created_at: dates_to_range(v)).count + end + + # Reverse hash r, so dates in ascending order + r = r.to_a.reverse.to_h + + respond_to do |format| + format.json { render(json: r.to_json) } + format.csv do + send_data(CSV.generate do |csv| + csv << [_('Month'), _('No. Completed Plans')] + total = 0 + r.each_pair do |k, v| + csv << [k, v] + total += v + end + csv << [_('Total'), total] + end, filename: "#{_('completed_plans')}.csv") end - csv << [_("Total"), total] - end, filename: "#{_('completed_plans')}.csv") + end + else + if params['start_date'].present? || params['end_date'].present? + scoped = scoped.where(created_at: dates_to_range(params)) + end + render(json: { completed_plans: scoped.count }) end end - else - if params["start_date"].present? || params["end_date"].present? - scoped = scoped.where(created_at: dates_to_range(params)) - end - render(json: { completed_plans: scoped.count }) - end - end - # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - # rubocop:enable - - # /api/v0/statistics/created_plans - # Returns the number of created plans within the user's org for the data - # start_date and end_date specified - # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - def created_plans - raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans? - - scoped = if @user.can_super_admin? && params[:org_id].present? - Org.find(params[:org_id]).plans - else - @user.org.plans - end - - if params[:range_dates].present? - r = {} - params[:range_dates].each_pair do |k, v| - r[k] = scoped.where(created_at: dates_to_range(v)).count - end - - # Reverse hash r, so dates in ascending order - r = Hash[r.to_a.reverse] - - respond_to do |format| - format.json { render(json: r.to_json) } - format.csv do - send_data(CSV.generate do |csv| - csv << [_("Month"), _("No. Plans")] - total = 0 - r.each_pair do |k, v| - csv << [k, v] - total += v + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + + # /api/v0/statistics/created_plans + # Returns the number of created plans within the user's org for the data + # start_date and end_date specified + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + def created_plans + raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans? + + scoped = if @user.can_super_admin? && params[:org_id].present? + Org.find(params[:org_id]).plans + else + @user.org.plans + end + + if params[:range_dates].present? + r = {} + params[:range_dates].each_pair do |k, v| + r[k] = scoped.where(created_at: dates_to_range(v)).count + end + + # Reverse hash r, so dates in ascending order + r = r.to_a.reverse.to_h + + respond_to do |format| + format.json { render(json: r.to_json) } + format.csv do + send_data(CSV.generate do |csv| + csv << [_('Month'), _('No. Plans')] + total = 0 + r.each_pair do |k, v| + csv << [k, v] + total += v + end + csv << [_('Total'), total] + end, filename: "#{_('plans')}.csv") end - csv << [_("Total"), total] - end, filename: "#{_('plans')}.csv") + end + else + if params['start_date'].present? || params['end_date'].present? + scoped = scoped.where(created_at: dates_to_range(params)) + end + render(json: { completed_plans: scoped.count }) end end - else - if params["start_date"].present? || params["end_date"].present? - scoped = scoped.where(created_at: dates_to_range(params)) + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + + ## + # Displays the number of DMPs using templates owned/create by the caller's Org + # between the optional specified dates + # rubocop:disable Metrics/AbcSize + def using_template + org_templates = @user.org.templates.where(customization_of: nil) + raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, + org_templates.first).using_template? + + @templates = {} + org_templates.each do |template| + if @templates[template.title].blank? + @templates[template.title] = {} + @templates[template.title][:title] = template.title + @templates[template.title][:id] = template.family_id + @templates[template.title][:uses] = 0 + end + scoped = template.plans + if params['start_date'].present? || params['end_date'].present? + scoped = scoped.where(created_at: dates_to_range(params)) + end + @templates[template.title][:uses] += scoped.length + end + respond_with @templates end - render(json: { completed_plans: scoped.count }) - end - end - # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - # rubocop:enable - - ## - # Displays the number of DMPs using templates owned/create by the caller's Org - # between the optional specified dates - # rubocop:disable Metrics/AbcSize - def using_template - org_templates = @user.org.templates.where(customization_of: nil) - unless Api::V0::StatisticsPolicy.new(@user, org_templates.first).using_template? - raise Pundit::NotAuthorizedError - end - - @templates = {} - org_templates.each do |template| - if @templates[template.title].blank? - @templates[template.title] = {} - @templates[template.title][:title] = template.title - @templates[template.title][:id] = template.family_id - @templates[template.title][:uses] = 0 + # rubocop:enable Metrics/AbcSize + + ## + # GET + # Renders a list of templates with their titles, ids, and uses between the optional + # specified dates the uses are restricted to DMPs created by users of the same + # organisation as the user who ititiated the call. + # rubocop:disable Metrics/AbcSize + def plans_by_template + raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans_by_template? + + @templates = {} + scoped = @user.org.plans + if params['start_date'].present? || params['end_date'].present? + scoped = scoped.where(created_at: dates_to_range(params)) + end + scoped.each do |plan| + # if hash exists + if @templates[plan.template.title].blank? + @templates[plan.template.title] = {} + @templates[plan.template.title][:title] = plan.template.title + @templates[plan.template.title][:id] = plan.template.family_id + @templates[plan.template.title][:uses] = 1 + else + @templates[plan.template.title][:uses] += 1 + end + end + respond_with @templates end - scoped = template.plans - if params["start_date"].present? || params["end_date"].present? - scoped = scoped.where(created_at: dates_to_range(params)) + # rubocop:enable Metrics/AbcSize + + # GET + # + # Renders a list of DMPs metadata, provided the DMPs were created between the + # optional specified dates DMPs must be owned by a user who's organisation is the + # same as the user who generates the call. + # rubocop:disable Metrics/AbcSize + def plans + raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans? + + @org_plans = @user.org.plans + if params['remove_tests'].present? && params['remove_tests'].downcase == 'true' + @org_plans = @org_plans.where.not(visibility: Plan.visibilities[:is_test]) + end + if params['start_date'].present? || params['end_date'].present? + @org_plans = @org_plans.where(created_at: dates_to_range(params)) + end + respond_with @org_plans end - @templates[template.title][:uses] += scoped.length - end - respond_with @templates - end - # rubocop:enable Metrics/AbcSize - - ## - # GET - # Renders a list of templates with their titles, ids, and uses between the optional - # specified dates the uses are restricted to DMPs created by users of the same - # organisation as the user who ititiated the call. - # rubocop:disable Metrics/AbcSize - def plans_by_template - unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans_by_template? - raise Pundit::NotAuthorizedError - end + # rubocop:enable Metrics/AbcSize - @templates = {} - scoped = @user.org.plans - if params["start_date"].present? || params["end_date"].present? - scoped = scoped.where(created_at: dates_to_range(params)) - end - scoped.each do |plan| - # if hash exists - if @templates[plan.template.title].blank? - @templates[plan.template.title] = {} - @templates[plan.template.title][:title] = plan.template.title - @templates[plan.template.title][:id] = plan.template.family_id - @templates[plan.template.title][:uses] = 1 - else - @templates[plan.template.title][:uses] += 1 + private + + # Convert start/end dates in hash to a range of Dates + def dates_to_range(hash) + today = Date.today + start_date = Date.parse(hash.fetch('start_date', today.prev_month.to_date.to_s)) + end_date = Date.parse(hash.fetch('end_date', today.to_date.to_s)) + 1.day + start_date..end_date end end - respond_with @templates - end - # rubocop:enable Metrics/AbcSize - - # GET - # - # Renders a list of DMPs metadata, provided the DMPs were created between the - # optional specified dates DMPs must be owned by a user who's organisation is the - # same as the user who generates the call. - # rubocop:disable Metrics/AbcSize - def plans - raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans? - - @org_plans = @user.org.plans - if params["remove_tests"].present? && params["remove_tests"].downcase == "true" - @org_plans = @org_plans.where.not(visibility: Plan.visibilities[:is_test]) - end - if params["start_date"].present? || params["end_date"].present? - @org_plans = @org_plans.where(created_at: dates_to_range(params)) - end - respond_with @org_plans end - # rubocop:enable Metrics/AbcSize - - private - - # Convert start/end dates in hash to a range of Dates - def dates_to_range(hash) - today = Date.today - start_date = Date.parse(hash.fetch("start_date", today.prev_month.to_date.to_s)) - end_date = Date.parse(hash.fetch("end_date", today.to_date.to_s)) + 1.day - start_date..end_date - end - end diff --git a/app/controllers/api/v0/templates_controller.rb b/app/controllers/api/v0/templates_controller.rb index b4f8e1e243..f1156593f5 100644 --- a/app/controllers/api/v0/templates_controller.rb +++ b/app/controllers/api/v0/templates_controller.rb @@ -1,58 +1,59 @@ # frozen_string_literal: true -class Api::V0::TemplatesController < Api::V0::BaseController - - before_action :authenticate - - # GET - # - # Renders a list of templates ordered by organisation - # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - def index - # check if the user has permissions to use the templates API - unless Api::V0::TemplatePolicy.new(@user, :guidance_group).index? - raise Pundit::NotAuthorizedError - end - - @org_templates = {} - - published_templates = Template.includes(:org) - .unarchived - .where(customization_of: nil, published: true) - .order(:org_id, :version) - - customized_templates = Template.includes(:org) - .unarchived - .where(org_id: @user.org_id, published: true) - .where.not(customization_of: nil) - - published_templates.order(:org_id, :version).each do |temp| - if @org_templates[temp.org].present? - if @org_templates[temp.org][:own][temp.family_id].nil? - @org_templates[temp.org][:own][temp.family_id] = temp +module Api + module V0 + # Handles queries for templates for API V0 + class TemplatesController < Api::V0::BaseController + before_action :authenticate + + # GET + # + # Renders a list of templates ordered by organisation + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + def index + # check if the user has permissions to use the templates API + raise Pundit::NotAuthorizedError unless Api::V0::TemplatePolicy.new(@user, :guidance_group).index? + + @org_templates = {} + + published_templates = Template.includes(:org) + .unarchived + .where(customization_of: nil, published: true) + .order(:org_id, :version) + + customized_templates = Template.includes(:org) + .unarchived + .where(org_id: @user.org_id, published: true) + .where.not(customization_of: nil) + + published_templates.order(:org_id, :version).each do |temp| + if @org_templates[temp.org].present? + @org_templates[temp.org][:own][temp.family_id] = temp if @org_templates[temp.org][:own][temp.family_id].nil? + else + @org_templates[temp.org] = {} + @org_templates[temp.org][:own] = {} + @org_templates[temp.org][:cust] = {} + @org_templates[temp.org][:own][temp.family_id] = temp + end end - else - @org_templates[temp.org] = {} - @org_templates[temp.org][:own] = {} - @org_templates[temp.org][:cust] = {} - @org_templates[temp.org][:own][temp.family_id] = temp - end - end - customized_templates.each do |temp| - if @org_templates[temp.org].present? - if @org_templates[temp.org][:cust][temp.family_id].nil? - @org_templates[temp.org][:cust][temp.family_id] = temp + customized_templates.each do |temp| + if @org_templates[temp.org].present? + if @org_templates[temp.org][:cust][temp.family_id].nil? + @org_templates[temp.org][:cust][temp.family_id] = + temp + end + else + @org_templates[temp.org] = {} + @org_templates[temp.org][:own] = {} + @org_templates[temp.org][:cust] = {} + @org_templates[temp.org][:cust][temp.family_id] = temp + end end - else - @org_templates[temp.org] = {} - @org_templates[temp.org][:own] = {} - @org_templates[temp.org][:cust] = {} - @org_templates[temp.org][:cust][temp.family_id] = temp + respond_with @org_templates end + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity end - respond_with @org_templates end - # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - # rubocop:enable - end diff --git a/app/controllers/api/v1/authentication_controller.rb b/app/controllers/api/v1/authentication_controller.rb index 752bfbb117..c74dd39c5d 100644 --- a/app/controllers/api/v1/authentication_controller.rb +++ b/app/controllers/api/v1/authentication_controller.rb @@ -1,9 +1,7 @@ # frozen_string_literal: true module Api - module V1 - # Accepts 2 types of authentication: # # Client Credentials: @@ -24,12 +22,12 @@ module V1 # code: "[users.api_token]" # } class AuthenticationController < BaseApiController - respond_to :json skip_before_action :authorize_request, only: %i[authenticate] # POST /api/v1/authenticate + # rubocop:disable Metrics/AbcSize def authenticate body = request.body.read json = JSON.parse(body) @@ -38,20 +36,17 @@ def authenticate if @token.present? @expiration = auth_svc.expiration - @token_type = "Bearer" - render "/api/v1/token", status: :ok + @token_type = 'Bearer' + render '/api/v1/token', status: :ok else render_error errors: auth_svc.errors, status: :unauthorized end rescue JSON::ParserError => e Rails.logger.error "API V1 - authenticate: #{e.message}" Rails.logger.error request.body.read - render_error errors: _("Missing or invalid JSON"), status: :bad_request + render_error errors: _('Missing or invalid JSON'), status: :bad_request end - # rubocop:enable - + # rubocop:enable Metrics/AbcSize end - end - end diff --git a/app/controllers/api/v1/base_api_controller.rb b/app/controllers/api/v1/base_api_controller.rb index 77da394d82..e25a6740a7 100644 --- a/app/controllers/api/v1/base_api_controller.rb +++ b/app/controllers/api/v1/base_api_controller.rb @@ -1,12 +1,9 @@ # frozen_string_literal: true module Api - module V1 - # Base API Controller class BaseApiController < ApplicationController - # Skipping the standard Rails authenticity tokens passed in UI skip_before_action :verify_authenticity_token @@ -26,14 +23,14 @@ class BaseApiController < ApplicationController # GET /api/v1/heartbeat def heartbeat - render "/api/v1/heartbeat", status: :ok + render '/api/v1/heartbeat', status: :ok end protected def render_error(errors:, status:) @payload = { errors: [errors] } - render "/api/v1/error", status: status + render '/api/v1/error', status: status end private @@ -63,12 +60,13 @@ def base_response_content # Retrieve the requested pagination params or use defaults # only allow 100 per page as the max def pagination_params - @page = params.fetch("page", 1).to_i - @per_page = params.fetch("per_page", 20).to_i + @page = params.fetch('page', 1).to_i + @per_page = params.fetch('per_page', 20).to_i @per_page = 100 if @per_page > 100 end # Parse the body of the incoming request + # rubocop:disable Metrics/AbcSize def parse_request return false unless request.present? && request.body.present? @@ -78,10 +76,11 @@ def parse_request rescue JSON::ParserError => e Rails.logger.error "JSON Parser: #{e.message}" Rails.logger.error request.body - render_error(errors: _("Invalid JSON format"), status: :bad_request) + render_error(errors: _('Invalid JSON format'), status: :bad_request) false end end + # rubocop:enable Metrics/AbcSize # ========================== @@ -189,9 +188,6 @@ def host_permitted_params storage_type availability geo_location certified_with pid_system] + [host_ids: identifier_permitted_params] end - end - end - end diff --git a/app/controllers/api/v1/plans_controller.rb b/app/controllers/api/v1/plans_controller.rb index 649f987d97..b1480437bd 100644 --- a/app/controllers/api/v1/plans_controller.rb +++ b/app/controllers/api/v1/plans_controller.rb @@ -1,11 +1,9 @@ # frozen_string_literal: true module Api - module V1 - + # Handles CRUD operations for plans in API V1 class PlansController < BaseApiController - respond_to :json # GET /api/v1/plans/:id @@ -15,14 +13,15 @@ def show if plans.present? && plans.any? @items = paginate_response(results: plans) - render "/api/v1/plans/index", status: :ok + render '/api/v1/plans/index', status: :ok else - render_error(errors: [_("Plan not found")], status: :not_found) + render_error(errors: [_('Plan not found')], status: :not_found) end end # POST /api/v1/plans # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def create dmp = @json.with_indifferent_access.fetch(:items, []).first.fetch(:dmp, {}) @@ -34,8 +33,8 @@ def create # Convert the JSON into a Plan and it's associations plan = Api::V1::Deserialization::Plan.deserialize(json: dmp) if plan.present? - save_err = _("Unable to create your DMP") - exists_err = _("Plan already exists. Send an update instead.") + save_err = _('Unable to create your DMP') + exists_err = _('Plan already exists. Send an update instead.') no_org_err = _("Could not determine ownership of the DMP. Please add an :affiliation to the :contact") @@ -55,11 +54,8 @@ def create # If we cannot save for some reason then return an error plan = Api::V1::PersistenceService.safe_save(plan: plan) - # rubocop:disable Layout/LineLength render_error(errors: save_err, status: :internal_server_error) and return if plan.new_record? - # rubocop:enable Layout/LineLength - # If the plan was generated by an ApiClient then associate them plan.update(api_client_id: client.id) if client.is_a?(ApiClient) @@ -69,14 +65,15 @@ def create # Kaminari Pagination requires an ActiveRecord result set :/ @items = paginate_response(results: Plan.where(id: plan.id)) - render "/api/v1/plans/index", status: :created + render '/api/v1/plans/index', status: :created else - render_error(errors: [_("Invalid JSON!")], status: :bad_request) + render_error(errors: [_('Invalid JSON!')], status: :bad_request) end rescue JSON::ParserError - render_error(errors: [_("Invalid JSON")], status: :bad_request) + render_error(errors: [_('Invalid JSON')], status: :bad_request) end # rubocop:enable Metrics/AbcSize, Metrics/MethodLength + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity # GET /api/v1/plans def index @@ -88,9 +85,9 @@ def index if plans.present? && plans.any? @items = paginate_response(results: plans) @minimal = true - render "api/v1/plans/index", status: :ok + render 'api/v1/plans/index', status: :ok else - render_error(errors: [_("No Plans found")], status: :not_found) + render_error(errors: [_('No Plans found')], status: :not_found) end end @@ -134,11 +131,12 @@ def lookup_user(contributor:) user end + # rubocop:disable Metrics/AbcSize def invite_contributor(contributor:) return nil unless contributor.present? # If the user was not found, invite them and attach any know identifiers - names = contributor.name&.split || [""] + names = contributor.name&.split || [''] firstname = names.length > 1 ? names.first : nil surname = names.length > 1 ? names.last : names.first user = User.invite!({ email: contributor.email, @@ -153,9 +151,7 @@ def invite_contributor(contributor:) end user end - + # rubocop:enable Metrics/AbcSize end - end - end diff --git a/app/controllers/api/v1/templates_controller.rb b/app/controllers/api/v1/templates_controller.rb index 57383c825c..729b3edbbd 100644 --- a/app/controllers/api/v1/templates_controller.rb +++ b/app/controllers/api/v1/templates_controller.rb @@ -1,14 +1,13 @@ # frozen_string_literal: true module Api - module V1 - + # Provides a list of templates for API V1 class TemplatesController < BaseApiController - respond_to :json # GET /api/v1/templates + # rubocop:disable Metrics/AbcSize def index # If this is a User and not an ApiClient include the Org's # templates and customizations as well as the public ones @@ -35,12 +34,10 @@ def index templates = templates.order(:title) @items = paginate_response(results: templates) - render "/api/v1/templates/index", status: :ok + render '/api/v1/templates/index', status: :ok end # rubocop:enable - end - + # rubocop:enable Metrics/AbcSize end - end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 53dad81fb4..e3f3851f2c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true +# Base controller logic class ApplicationController < ActionController::Base - protect_from_forgery with: :exception before_action :configure_permitted_parameters, if: :devise_controller? @@ -35,11 +35,11 @@ def current_org def user_not_authorized if user_signed_in? # redirect_to plans_url, alert: _("You are not authorized to perform this action.") - msg = _("You are not authorized to perform this action.") + msg = _('You are not authorized to perform this action.') render_respond_to_format_with_error_message(msg, plans_url, 403, nil) else # redirect_to root_url, alert: _("You need to sign in or sign up before continuing.") - msg = _("You need to sign in or sign up before continuing.") + msg = _('You need to sign in or sign up before continuing.') render_respond_to_format_with_error_message(msg, root_url, 401, nil) end end @@ -56,15 +56,16 @@ def current_locale def store_location # store last url - this is needed for post-login redirect to whatever the user last # visited. - unless ["/users/sign_in", - "/users/sign_up", - "/users/password", - "/users/invitation/accept"].any? { |ur| request.fullpath.include?(ur) } \ - or request.xhr? # don't store ajax calls + unless ['/users/sign_in', + '/users/sign_up', + '/users/password', + '/users/invitation/accept'].any? { |ur| request.fullpath.include?(ur) } \ + || request.xhr? # don't store ajax calls session[:previous_url] = request.fullpath end end + # rubocop:disable Metrics/AbcSize def after_sign_in_path_for(_resource) referer_path = URI(request.referer).path unless request.referer.nil? if from_external_domain? || referer_path.eql?(new_user_session_path) || @@ -75,6 +76,7 @@ def after_sign_in_path_for(_resource) request.referer end end + # rubocop:enable Metrics/AbcSize def after_sign_up_path_for(_resource) referer_path = URI(request.referer).path unless request.referer.nil? @@ -104,45 +106,42 @@ def authenticate_admin! end end - def failure_message(obj, action = "save") - _("Unable to %{action} the %{object}.%{errors}") % { - object: obj_name_for_display(obj), - action: action || "save", - errors: errors_for_display(obj) - } + def failure_message(obj, action = 'save') + format(_('Unable to %s the %s.%s'), + object: obj_name_for_display(obj), + action: action || 'save', errors: errors_for_display(obj)) end - def success_message(obj, action = "saved") - _("Successfully %{action} the %{object}.") % { - object: obj_name_for_display(obj), - action: action || "save" - } + def success_message(obj, action = 'saved') + format(_('Successfully %s the %s.'), object: obj_name_for_display(obj), action: action || 'save') end def errors_for_display(obj) - return "" unless obj.present? && obj.errors.any? + return '' unless obj.present? && obj.errors.any? msgs = obj.errors.full_messages.uniq.collect { |msg| "
  • #{msg}
  • " } - "
      #{msgs.join('')}
    " + "
      #{msgs.join}
    " end + # rubocop:disable Metrics/AbcSize def obj_name_for_display(obj) display_name = { - ApiClient: _("API client"), - ExportedPlan: _("plan"), - GuidanceGroup: _("guidance group"), - Note: _("comment"), - Org: _("organisation"), - Perm: _("permission"), - Pref: _("preferences"), - User: obj == current_user ? _("profile") : _("user"), - QuestionOption: _("question option") + ApiClient: _('API client'), + ExportedPlan: _('plan'), + GuidanceGroup: _('guidance group'), + Note: _('comment'), + Org: _('organisation'), + Perm: _('permission'), + Pref: _('preferences'), + User: obj == current_user ? _('profile') : _('user'), + QuestionOption: _('question option') } if obj.respond_to?(:customization_of) && obj.send(:customization_of).present? - display_name[:Template] = "customization" + display_name[:Template] = 'customization' end - display_name[obj.class.name.to_sym] || obj.class.name.downcase || "record" + display_name[obj.class.name.to_sym] || obj.class.name.downcase || 'record' end + # rubocop:enable Metrics/AbcSize # Override rails default render action to look for a branded version of a # template instead of using the default one. If no override exists, the @@ -152,7 +151,7 @@ def obj_name_for_display(obj) # replacing. For example: # app/views/branded/layouts/_header.html.erb -> app/views/layouts/_header.html.erb def prepend_view_paths - prepend_view_path Rails.root.join("app", "views", "branded") + prepend_view_path Rails.root.join('app', 'views', 'branded') end ## @@ -181,7 +180,7 @@ def configure_permitted_parameters end def render_not_found(exception) - msg = _("Record Not Found") + ": #{exception.message}" + msg = _('Record Not Found') + ": #{exception.message}" render_respond_to_format_with_error_message(msg, root_url, 404, exception) end @@ -200,9 +199,8 @@ def render_respond_to_format_with_error_message(msg, url_or_path, http_status, e # Render the JSON error message (using API V1) format.json do @payload = { errors: [msg] } - render "/api/v1/error", status: http_status + render '/api/v1/error', status: http_status end end end - end diff --git a/app/controllers/concerns/allowed_question_formats.rb b/app/controllers/concerns/allowed_question_formats.rb index 0dc68f3af7..3e8d4bd995 100644 --- a/app/controllers/concerns/allowed_question_formats.rb +++ b/app/controllers/concerns/allowed_question_formats.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true +# Controller that gets Questions types that allow multiple selections +# TODO: this could likely just live on the model! module AllowedQuestionFormats - private # The QuestionFormat "Multi select box" is no longer being used for new templates def allowed_question_formats - QuestionFormat.where.not(title: "Multi select box").order(:title) + QuestionFormat.where.not(title: 'Multi select box').order(:title) end - end diff --git a/app/controllers/concerns/conditional_user_mailer.rb b/app/controllers/concerns/conditional_user_mailer.rb index c9f5ce42e1..c83338347d 100644 --- a/app/controllers/concerns/conditional_user_mailer.rb +++ b/app/controllers/concerns/conditional_user_mailer.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true +# Determines whether or not the user has enabled/disabled the email notification +# before sending it out module ConditionalUserMailer - # Executes a given block passed if the recipient user has the preference # email key enabled # @@ -10,18 +11,17 @@ module ConditionalUserMailer # prefences.email (see dmproadmap.rb initializer) # # Returns Boolean - def deliver_if(recipients: [], key:, &block) + def deliver_if(key:, recipients: [], &block) return false unless block_given? Array(recipients).each do |recipient| - email_hash = recipient.get_preferences("email").with_indifferent_access + email_hash = recipient.get_preferences('email').with_indifferent_access # Violation of rubocop's DoubleNegation check # preference_value = !!email_hash.dig(*key.to_s.split(".")) - preference_value = email_hash.dig(*key.to_s.split(".")) + preference_value = email_hash.dig(*key.to_s.split('.')) block.call(recipient) if preference_value end true end - end diff --git a/app/controllers/concerns/org_selectable.rb b/app/controllers/concerns/org_selectable.rb index 5aac93cc48..223cf5a6a2 100644 --- a/app/controllers/concerns/org_selectable.rb +++ b/app/controllers/concerns/org_selectable.rb @@ -54,7 +54,6 @@ # # See the comments on OrgsController#search for more info on how the typeaheads work module OrgSelectable - extend ActiveSupport::Concern # rubocop:disable Metrics/BlockLength @@ -125,11 +124,10 @@ def create_org(org:, params_in:) end def prep_org_partial - name = Rails.configuration.x.application.restrict_orgs ? "local_only" : "combined" + name = Rails.configuration.x.application.restrict_orgs ? 'local_only' : 'combined' @org_partial = "shared/org_selectors/#{name}" @all_orgs = Org.includes(identifiers: [:identifier_scheme]).all end end # rubocop:enable Metrics/BlockLength - end diff --git a/app/controllers/concerns/paginable.rb b/app/controllers/concerns/paginable.rb index aea376ed12..34d73c95d6 100644 --- a/app/controllers/concerns/paginable.rb +++ b/app/controllers/concerns/paginable.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true +# Provides support for pagination/searching/sorting of table data # rubocop:disable Metrics/ModuleLength module Paginable - extend ActiveSupport::Concern - require "sort_direction" + require 'sort_direction' ## # Regex to validate sort_field param is safe @@ -37,15 +37,16 @@ module Paginable # one approach to just include everything in the double splat `**options` param # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/ParameterLists + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def paginable_renderise(partial: nil, template: nil, controller: nil, action: nil, path_params: {}, query_params: {}, scope: nil, locals: {}, **options) unless scope.is_a?(ActiveRecord::Relation) - raise ArgumentError, _("scope should be an ActiveRecord::Relation object") + raise ArgumentError, _('scope should be an ActiveRecord::Relation object') end - raise ArgumentError, _("path_params should be a Hash object") unless path_params.is_a?(Hash) - raise ArgumentError, _("query_params should be a Hash object") unless query_params.is_a?(Hash) - raise ArgumentError, _("locals should be a Hash object") unless locals.is_a?(Hash) + raise ArgumentError, _('path_params should be a Hash object') unless path_params.is_a?(Hash) + raise ArgumentError, _('query_params should be a Hash object') unless query_params.is_a?(Hash) + raise ArgumentError, _('locals should be a Hash object') unless locals.is_a?(Hash) # Default options @paginable_options = {}.merge(options) @@ -61,12 +62,12 @@ def paginable_renderise(partial: nil, template: nil, controller: nil, action: ni # Additional path_params passed to this function got special treatment # (e.g. it is taking into account when building base_url) @paginable_path_params = path_params.symbolize_keys - if @args[:page] == "ALL" && + if @args[:page] == 'ALL' && @args[:search].blank? && @paginable_options[:view_all] == false render( status: :forbidden, - html: _("Restricted access to View All the records") + html: _('Restricted access to View All the records') ) else @refined_scope = refine_query(scope) @@ -78,17 +79,17 @@ def paginable_renderise(partial: nil, template: nil, controller: nil, action: ni ) # If this was an ajax call then render as JSON if options[:format] == :json - render json: { html: render_to_string(layout: "/layouts/paginable", + render json: { html: render_to_string(layout: '/layouts/paginable', partial: partial, locals: locals) } elsif partial.present? - render(layout: "/layouts/paginable", partial: partial, locals: locals) + render(layout: '/layouts/paginable', partial: partial, locals: locals) else render(template: template, locals: locals) end end end # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/ParameterLists - # rubocop:enable + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity # Returns the base url of the paginable route for a given page passed def paginable_base_url(page = 1) @@ -107,7 +108,7 @@ def paginable_sort_link(sort_field) link_to( sort_link_name(sort_field), sort_link_url(sort_field), - class: "paginable-action", + class: 'paginable-action', data: { remote: @paginable_options[:remote] }, aria: { label: sort_field } ) @@ -125,21 +126,21 @@ def paginable? # Refine a scope passed to this concern if any of the params (search, # sort_field or page) are present - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def refine_query(scope) @args = @args.with_indifferent_access scope = scope.search(@args[:search]) if @args[:search].present? # Can raise NoMethodError if the scope does not define a search method if @args[:sort_field].present? frmt = @args[:sort_field][SORT_COLUMN_FORMAT] - raise ArgumentError, "sort_field param looks unsafe" unless frmt + raise ArgumentError, 'sort_field param looks unsafe' unless frmt # Can raise ActiveRecord::StatementInvalid (e.g. column does not # exist, ambiguity on column, etc) # how we contruct scope depends on whether sort field is in the # main table or in a related table scope_table = scope.klass.name.underscore - parts = @args[:sort_field].partition(".") + parts = @args[:sort_field].partition('.') table_part = parts.first column_part = parts.last if scope_table == table_part.singularize @@ -148,16 +149,16 @@ def refine_query(scope) else order_field = ActiveRecord::Base.sanitize_sql(@args[:sort_field]) scope = scope.includes(table_part.singularize.to_sym) - .order(order_field + " " + sort_direction.to_s) + .order("#{order_field} #{sort_direction}") end end - if @args[:page] != "ALL" + if @args[:page] != 'ALL' # Can raise error if page is not a number scope = scope.page(@args[:page]) end scope end - # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength def sort_direction @sort_direction ||= SortDirection.new(@args[:sort_direction]) @@ -167,9 +168,9 @@ def sort_direction # html prevented of being escaped def sort_link_name(sort_field) @args = @args.with_indifferent_access - class_name = "fas fa-sort" - dir = "up" - dir = "down" if sort_direction.to_s == "DESC" + class_name = 'fas fa-sort' + dir = 'up' + dir = 'down' if sort_direction.to_s == 'DESC' class_name = "fas fa-sort-#{dir}" if @args[:sort_field] == sort_field <<~HTML.html_safe - #{_('Sort by %{sort_field}') % { sort_field: sort_field.split('.').first }} + #{format(_('Sort by %s'), sort_field: sort_field.split('.').first)} HTML end # Returns the sort url for a given sort_field. + # rubocop:disable Metrics/AbcSize def sort_link_url(sort_field) @args = @args.with_indifferent_access query_params = {} - query_params[:page] = @args[:page] == "ALL" ? "ALL" : 1 + query_params[:page] = @args[:page] == 'ALL' ? 'ALL' : 1 query_params[:sort_field] = sort_field query_params[:sort_direction] = if @args[:sort_field] == sort_field sort_direction.opposite @@ -200,6 +202,7 @@ def sort_link_url(sort_field) sort_url.to_s "#{sort_url}&#{stringify_nonpagination_query_params}" end + # rubocop:enable Metrics/AbcSize # Retrieve any query params that are not a part of the paginable concern def stringify_nonpagination_query_params @@ -211,10 +214,10 @@ def stringify_query_params(page: 1, search: @args[:search], sort_direction: nil) query_string = { page: page } - query_string["search"] = search if search.present? + query_string['search'] = search if search.present? if sort_field.present? - query_string["sort_field"] = sort_field - query_string["sort_direction"] = SortDirection.new(sort_direction) + query_string['sort_field'] = sort_field + query_string['sort_direction'] = SortDirection.new(sort_direction) end query_string.to_param end @@ -222,6 +225,5 @@ def stringify_query_params(page: 1, search: @args[:search], def paginable_params params.permit(PAGINATION_QUERY_PARAMS) end - end # rubocop:enable Metrics/ModuleLength diff --git a/app/controllers/concerns/template_methods.rb b/app/controllers/concerns/template_methods.rb index bebd8249a2..f1ebf5d862 100644 --- a/app/controllers/concerns/template_methods.rb +++ b/app/controllers/concerns/template_methods.rb @@ -1,13 +1,10 @@ # frozen_string_literal: true # This module holds helper controller methods for controllers that deal with Templates -# module TemplateMethods - private def template_type(template) - template.customization_of.present? ? _("customisation") : _("template") + template.customization_of.present? ? _('customisation') : _('template') end - end diff --git a/app/controllers/concerns/versionable.rb b/app/controllers/concerns/versionable.rb index 24233e4ef9..e242f16e78 100644 --- a/app/controllers/concerns/versionable.rb +++ b/app/controllers/concerns/versionable.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true +# Helpers that allow us to version Template-Phase-Section-Question module Versionable - private # Takes in a Template, phase, Section, Question, or Annotaion @@ -18,7 +18,7 @@ def get_modifiable(obj) template = obj else raise ArgumentError, - _("obj should be a Template, Phase, Section, Question, or Annotation") + _('obj should be a Template, Phase, Section, Question, or Annotation') end # raises RuntimeError if template is not latest @@ -39,11 +39,12 @@ def get_modifiable(obj) # generated and returns a modifiable version of that object # NOTE: the obj passed is still not saved however it should belongs to a # parent already - # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity def get_new(obj) unless obj.respond_to?(:template) raise ArgumentError, - _("obj should be a Phase, Section, Question, or Annotation") + _('obj should be a Phase, Section, Question, or Annotation') end template = obj.template @@ -62,7 +63,7 @@ def get_new(obj) belongs = :question else raise ArgumentError, - _("obj should be a Phase, Section, Question, or Annotation") + _('obj should be a Phase, Section, Question, or Annotation') end if belongs == :template @@ -76,21 +77,21 @@ def get_new(obj) end obj end - # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength + # rubocop:enable Metrics/CyclomaticComplexity # Locates an object (e.g. phase, section, question, annotation) in a # search_space # (e.g. phases/sections/questions/annotations) by comparing either the number # method or the org_id and text for annotations # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def find_in_space(obj, search_space) - unless search_space.respond_to?(:each) - raise ArgumentError, _("The search_space does not respond to each") - end + raise ArgumentError, _('The search_space does not respond to each') unless search_space.respond_to?(:each) if search_space.empty? raise ArgumentError, - _("The search space does not have elements associated") + _('The search space does not have elements associated') end if obj.is_a?(search_space.first.class) @@ -131,6 +132,5 @@ def find_in_space(obj, search_space) nil end # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - # rubocop:enable - + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity end diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb index 9857fb6c1b..ca95d2fa3d 100644 --- a/app/controllers/contacts_controller.rb +++ b/app/controllers/contacts_controller.rb @@ -1,39 +1,43 @@ # frozen_string_literal: true -class ContactUs::ContactsController < ApplicationController +module ContactUs + # Controller for the Contact Us gem + class ContactsController < ApplicationController + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + def create + @contact = ContactUs::Contact.new(params[:contact_us_contact]) - def create - @contact = ContactUs::Contact.new(params[:contact_us_contact]) - - if !user_signed_in? && Rails.configuration.x.recaptcha.enabled - unless verify_recaptcha(model: @contact) && @contact.save - flash[:alert] = _("Captcha verification failed, please retry.") + if !user_signed_in? && Rails.configuration.x.recaptcha.enabled && + !(verify_recaptcha(model: @contact) && @contact.save) + flash[:alert] = _('Captcha verification failed, please retry.') render_new_page and return end + if @contact.save + redirect_to(ContactUs.success_redirect || '/', + notice: _('Contact email was successfully sent.')) + else + flash[:alert] = _('Unable to submit your request') + render_new_page + end end - if @contact.save - redirect_to(ContactUs.success_redirect || "/", - notice: _("Contact email was successfully sent.")) - else - flash[:alert] = _("Unable to submit your request") + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + + def new + @contact = ContactUs::Contact.new render_new_page end - end - def new - @contact = ContactUs::Contact.new - render_new_page - end - - protected + protected - def render_new_page - case ContactUs.form_gem - when "formtastic" then render "new_formtastic" - when "simple_form" then render "new_simple_form" - else - render "new" + def render_new_page + case ContactUs.form_gem + when 'formtastic' then render 'new_formtastic' + when 'simple_form' then render 'new_simple_form' + else + render 'new' + end end end - end diff --git a/app/controllers/contributors_controller.rb b/app/controllers/contributors_controller.rb index d5246f9a5b..0838f2756a 100644 --- a/app/controllers/contributors_controller.rb +++ b/app/controllers/contributors_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true +# Controller for the Contributors page class ContributorsController < ApplicationController - include OrgSelectable helper PaginableHelper @@ -27,7 +27,7 @@ def edit authorize @plan end - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength # POST /plans/:plan_id/contributors def create authorize @plan @@ -36,8 +36,8 @@ def create args = process_org(hash: args) if args.blank? @contributor = Contributor.new(args) - @contributor.errors.add(:affiliation, "invalid") - flash[:alert] = failure_message(@contributor, _("add")) + @contributor.errors.add(:affiliation, 'invalid') + flash[:alert] = failure_message(@contributor, _('add')) render :new else args = process_orcid_for_create(hash: args) @@ -51,14 +51,14 @@ def create save_orcid redirect_to plan_contributors_path(@plan), - notice: success_message(@contributor, _("added")) + notice: success_message(@contributor, _('added')) else - flash[:alert] = failure_message(@contributor, _("add")) + flash[:alert] = failure_message(@contributor, _('add')) render :new end end end - # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength # PUT /plans/:plan_id/contributors/:id def update @@ -69,9 +69,9 @@ def update if @contributor.update(args) redirect_to edit_plan_contributor_path(@plan, @contributor), - notice: success_message(@contributor, _("saved")) + notice: success_message(@contributor, _('saved')) else - flash.now[:alert] = failure_message(@contributor, _("save")) + flash.now[:alert] = failure_message(@contributor, _('save')) render :edit end end @@ -81,10 +81,10 @@ def update def destroy authorize @plan if @contributor.destroy - msg = success_message(@contributor, _("removed")) + msg = success_message(@contributor, _('removed')) redirect_to plan_contributors_path(@plan), notice: msg else - flash.now[:alert] = failure_message(@contributor, _("remove")) + flash.now[:alert] = failure_message(@contributor, _('remove')) render :edit end end @@ -105,7 +105,7 @@ def contributor_params # Translate the check boxes values of "1" and "0" to true/false def translate_roles(hash:) roles = Contributor.new.all_roles - roles.each { |role| hash[role.to_sym] = hash[role.to_sym] == "1" } + roles.each { |role| hash[role.to_sym] = hash[role.to_sym] == '1' } hash end @@ -130,7 +130,7 @@ def process_org(hash:) def process_orcid_for_create(hash:) return hash unless hash[:identifiers_attributes].present? - id_hash = hash[:identifiers_attributes][:"0"] + id_hash = hash[:identifiers_attributes][:'0'] return hash unless id_hash[:value].blank? hash.delete(:identifiers_attributes) @@ -141,10 +141,10 @@ def process_orcid_for_create(hash:) def process_orcid_for_update(hash:) return hash unless hash[:identifiers_attributes].present? - id_hash = hash[:identifiers_attributes][:"0"] + id_hash = hash[:identifiers_attributes][:'0'] return hash unless id_hash[:value].blank? - existing = @contributor.identifier_for_scheme(scheme: "orcid") + existing = @contributor.identifier_for_scheme(scheme: 'orcid') existing.destroy if existing.present? hash.delete(:identifiers_attributes) hash @@ -157,7 +157,7 @@ def fetch_plan @plan = Plan.includes(:contributors).find_by(id: params[:plan_id]) return true if @plan.present? - redirect_to root_path, alert: _("plan not found") + redirect_to root_path, alert: _('plan not found') end def fetch_contributor @@ -165,7 +165,7 @@ def fetch_contributor return true if @contributor.present? && @plan.contributors.include?(@contributor) - redirect_to plan_contributors_path, alert: _("contributor not found") + redirect_to plan_contributors_path, alert: _('contributor not found') end # The following 2 methods address an issue with using Rails normal @@ -195,5 +195,4 @@ def save_orcid @cached_orcid.save @contributor.reload end - end diff --git a/app/controllers/feedback_requests_controller.rb b/app/controllers/feedback_requests_controller.rb index 21ad271218..a8d91c4976 100644 --- a/app/controllers/feedback_requests_controller.rb +++ b/app/controllers/feedback_requests_controller.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true +# Controller that handles requests for Admin Feedback class FeedbackRequestsController < ApplicationController - include FeedbacksHelper after_action :verify_authorized - ALERT = _("Unable to submit your request for feedback at this time.") - ERROR = _("An error occurred when requesting feedback for this plan.") + ALERT = _('Unable to submit your request for feedback at this time.') + ERROR = _('An error occurred when requesting feedback for this plan.') def create @plan = Plan.find(params[:plan_id]) @@ -34,5 +34,4 @@ def request_feedback_flash_notice text = current_user.org.feedback_msg || feedback_confirmation_default_message feedback_constant_to_text(text, current_user, @plan, current_user.org) end - end diff --git a/app/controllers/guidance_groups_controller.rb b/app/controllers/guidance_groups_controller.rb index a20b2dd233..611d5ef4d4 100644 --- a/app/controllers/guidance_groups_controller.rb +++ b/app/controllers/guidance_groups_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true +# Controller for the Guidances page that handles Group info class GuidanceGroupsController < ApplicationController - after_action :verify_authorized respond_to :html @@ -18,6 +18,7 @@ def admin_new end # POST /org/admin/guidancegroup/:id/admin_create + # rubocop:disable Metrics/AbcSize def admin_create # Ensure that the user can only create GuidanceGroups for their Org args = guidance_group_params.to_h.merge({ org_id: current_user.org.id }) @@ -25,13 +26,14 @@ def admin_create authorize @guidance_group if @guidance_group.save - flash.now[:notice] = success_message(@guidance_group, _("created")) + flash.now[:notice] = success_message(@guidance_group, _('created')) render :admin_edit else - flash.now[:alert] = failure_message(@guidance_group, _("create")) + flash.now[:alert] = failure_message(@guidance_group, _('create')) render :admin_new end end + # rubocop:enable Metrics/AbcSize # GET /org/admin/guidancegroup/:id/admin_edit def admin_edit @@ -40,17 +42,19 @@ def admin_edit end # PUT /org/admin/guidancegroup/:id/admin_update + # rubocop:disable Metrics/AbcSize def admin_update @guidance_group = GuidanceGroup.find(params[:id]) authorize @guidance_group if @guidance_group.update(guidance_group_params) - flash.now[:notice] = success_message(@guidance_group, _("saved")) + flash.now[:notice] = success_message(@guidance_group, _('saved')) else - flash.now[:alert] = failure_message(@guidance_group, _("save")) + flash.now[:alert] = failure_message(@guidance_group, _('save')) end render :admin_edit end + # rubocop:enable Metrics/AbcSize # PUT /org/admin/guidancegroup/:id/admin_update_publish def admin_update_publish @@ -58,10 +62,10 @@ def admin_update_publish authorize @guidance_group if @guidance_group.update(published: true) - flash[:notice] = _("Your guidance group has been published and is now available to users.") + flash[:notice] = _('Your guidance group has been published and is now available to users.') else - flash[:alert] = failure_message(@guidance_group, _("publish")) + flash[:alert] = failure_message(@guidance_group, _('publish')) end redirect_to admin_index_guidance_path end @@ -72,11 +76,9 @@ def admin_update_unpublish authorize @guidance_group if @guidance_group.update(published: false) - # rubocop:disable Layout/LineLength - flash[:notice] = _("Your guidance group is no longer published and will not be available to users.") - # rubocop:enable Layout/LineLength + flash[:notice] = _('Your guidance group is no longer published and will not be available to users.') else - flash[:alert] = failure_message(@guidance_group, _("unpublish")) + flash[:alert] = failure_message(@guidance_group, _('unpublish')) end redirect_to admin_index_guidance_path end @@ -86,9 +88,9 @@ def admin_destroy @guidance_group = GuidanceGroup.find(params[:id]) authorize @guidance_group if @guidance_group.destroy - flash[:notice] = success_message(@guidance_group, _("deleted")) + flash[:notice] = success_message(@guidance_group, _('deleted')) else - flash[:alert] = failure_message(@guidance_group, _("delete")) + flash[:alert] = failure_message(@guidance_group, _('delete')) end redirect_to admin_index_guidance_path end @@ -98,5 +100,4 @@ def admin_destroy def guidance_group_params params.require(:guidance_group).permit(:org_id, :name, :published, :optional_subset) end - end diff --git a/app/controllers/guidances_controller.rb b/app/controllers/guidances_controller.rb index 74835bd073..d3a193a12e 100644 --- a/app/controllers/guidances_controller.rb +++ b/app/controllers/guidances_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true +# Controller for the Guidances page that handles Guidance operations class GuidancesController < ApplicationController - after_action :verify_authorized respond_to :html @@ -36,6 +36,7 @@ def admin_edit end # POST /org/admin/guidance/:id/admin_create + # rubocop:disable Metrics/AbcSize def admin_create @guidance = Guidance.new(guidance_params) authorize @guidance @@ -48,14 +49,16 @@ def admin_create guidance_group.save end end - flash.now[:notice] = success_message(@guidance, _("created")) + flash.now[:notice] = success_message(@guidance, _('created')) else - flash.now[:alert] = failure_message(@guidance, _("create")) + flash.now[:alert] = failure_message(@guidance, _('create')) end render :new_edit end + # rubocop:enable Metrics/AbcSize # PUT /org/admin/guidance/:id/admin_update + # rubocop:disable Metrics/AbcSize def admin_update @guidance = Guidance.find(params[:id]) authorize @guidance @@ -68,14 +71,16 @@ def admin_update guidance_group.save end end - flash.now[:notice] = success_message(@guidance, _("saved")) + flash.now[:notice] = success_message(@guidance, _('saved')) else - flash.now[:alert] = failure_message(@guidance, _("save")) + flash.now[:alert] = failure_message(@guidance, _('save')) end render :new_edit end + # rubocop:enable Metrics/AbcSize # DELETE /org/admin/guidance/:id/admin_destroy + # rubocop:disable Metrics/AbcSize def admin_destroy @guidance = Guidance.find(params[:id]) authorize @guidance @@ -85,46 +90,47 @@ def admin_destroy guidance_group.published = false guidance_group.save end - flash[:notice] = success_message(@guidance, _("deleted")) + flash[:notice] = success_message(@guidance, _('deleted')) else - flash[:alert] = failure_message(@guidance, _("delete")) + flash[:alert] = failure_message(@guidance, _('delete')) end redirect_to(action: :admin_index) end + # rubocop:enable Metrics/AbcSize # PUT /org/admin/guidance/:id/admin_publish + # rubocop:disable Metrics/AbcSize def admin_publish @guidance = Guidance.find(params[:id]) authorize @guidance if @guidance.update_attributes(published: true) guidance_group = GuidanceGroup.find(@guidance.guidance_group_id) - if !guidance_group.published? || guidance_group.published.nil? - guidance_group.update(published: true) - end - flash[:notice] = _("Your guidance has been published and is now available to users.") + guidance_group.update(published: true) if !guidance_group.published? || guidance_group.published.nil? + flash[:notice] = _('Your guidance has been published and is now available to users.') else - flash[:alert] = failure_message(@guidance, _("publish")) + flash[:alert] = failure_message(@guidance, _('publish')) end redirect_to(action: :admin_index) end + # rubocop:enable Metrics/AbcSize # PUT /org/admin/guidance/:id/admin_unpublish + # rubocop:disable Metrics/AbcSize def admin_unpublish @guidance = Guidance.find(params[:id]) authorize @guidance if @guidance.update_attributes(published: false) guidance_group = GuidanceGroup.find(@guidance.guidance_group_id) - unless guidance_group.guidances.where(published: true).exists? - guidance_group.update(published: false) - end - flash[:notice] = _("Your guidance is no longer published and will not be available to users.") + guidance_group.update(published: false) unless guidance_group.guidances.where(published: true).exists? + flash[:notice] = _('Your guidance is no longer published and will not be available to users.') else - flash[:alert] = failure_message(@guidance, _("unpublish")) + flash[:alert] = failure_message(@guidance, _('unpublish')) end redirect_to(action: :admin_index) end + # rubocop:enable Metrics/AbcSize private @@ -138,5 +144,4 @@ def ensure_default_group(org) GuidanceGroup.create_org_default(org) end - end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index e4ec75806a..e7409d75b3 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true +# Controller for the home page that users see when not logged in class HomeController < ApplicationController - include OrgSelectable respond_to :html @@ -18,15 +18,14 @@ def index name = current_user.name(false) # The RolesController defaults the firstname and surname (both required fields) # to 'FirstName' and 'Surname' when a plan is shared with an unknown user - if name == "First Name Surname" + if name == 'First Name Surname' redirect_to edit_user_registration_path else redirect_to plans_url end - elsif session["devise.shibboleth_data"].present? + elsif session['devise.shibboleth_data'].present? # NOTE: Update this to handle ORCiD as well when we enable it as a login method redirect_to new_user_registration_url end end - end diff --git a/app/controllers/identifiers_controller.rb b/app/controllers/identifiers_controller.rb index 9b90f2c8a3..07f3530b80 100644 --- a/app/controllers/identifiers_controller.rb +++ b/app/controllers/identifiers_controller.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true +# Controller that handles a user disassociating their Shib or ORCID on the profile page class IdentifiersController < ApplicationController - respond_to :html after_action :verify_authorized # DELETE /users/identifiers - # --------------------------------------------------------------------- + # rubocop:disable Metrics/AbcSize def destroy authorize Identifier user = User.find(current_user.id) @@ -15,16 +15,14 @@ def destroy # If the requested identifier belongs to the current user remove it if user.identifiers.include?(identifier) identifier.destroy! - flash[:notice] = _("Successfully unlinked your account from %{is}.") % { - is: identifier.identifier_scheme&.description - } + flash[:notice] = + format(_('Successfully unlinked your account from %s.'), is: identifier.identifier_scheme&.description) else - flash[:alert] = _("Unable to unlink your account from %{is}.") % { - is: identifier.identifier_scheme&.description - } + flash[:alert] = + format(_('Unable to unlink your account from %s.'), is: identifier.identifier_scheme&.description) end redirect_to edit_user_registration_path end - + # rubocop:enable Metrics/AbcSize end diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index a623a64fce..c9f5f57c4b 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true +# Controller for the Comments section of the Write Plan page class NotesController < ApplicationController - include ConditionalUserMailer - require "pp" + require 'pp' after_action :verify_authorized respond_to :html @@ -13,9 +13,7 @@ def create @note = Note.new @note.user_id = note_params[:user_id] # ensure user has access to plan BEFORE creating/finding answer - unless Plan.find_by(id: note_params[:plan_id]).readable_by?(@note.user_id) - raise Pundit::NotAuthorizedError - end + raise Pundit::NotAuthorizedError unless Plan.find_by(id: note_params[:plan_id]).readable_by?(@note.user_id) Answer.transaction do @answer = Answer.find_by( @@ -45,31 +43,31 @@ def create answer = @note.answer plan = answer.plan owner = plan.owner - deliver_if(recipients: owner, key: "users.new_comment") do |_r| + deliver_if(recipients: owner, key: 'users.new_comment') do |_r| UserMailer.new_comment(current_user, plan, answer).deliver_now end - @notice = success_message(@note, _("created")) + @notice = success_message(@note, _('created')) render(json: { - "notes" => { - "id" => note_params[:question_id], - "html" => render_to_string(partial: "layout", locals: { + 'notes' => { + 'id' => note_params[:question_id], + 'html' => render_to_string(partial: 'layout', locals: { plan: @plan, question: @question, answer: @answer }, formats: [:html]) }, - "title" => { - "id" => note_params[:question_id], - "html" => render_to_string(partial: "title", locals: { + 'title' => { + 'id' => note_params[:question_id], + 'html' => render_to_string(partial: 'title', locals: { answer: @answer }, formats: [:html]) } }.to_json, status: :created) else @status = false - @notice = failure_message(@note, _("create")) + @notice = failure_message(@note, _('create')) render json: { - "msg" => @notice + 'msg' => @notice }.to_json, status: :bad_request end end @@ -89,27 +87,27 @@ def update question_id = @note.answer.question_id.to_s if @note.update(note_params) - @notice = success_message(@note, _("saved")) + @notice = success_message(@note, _('saved')) render(json: { - "notes" => { - "id" => question_id, - "html" => render_to_string(partial: "layout", locals: { + 'notes' => { + 'id' => question_id, + 'html' => render_to_string(partial: 'layout', locals: { plan: @plan, question: @question, answer: @answer }, formats: [:html]) }, - "title" => { - "id" => question_id, - "html" => render_to_string(partial: "title", locals: { + 'title' => { + 'id' => question_id, + 'html' => render_to_string(partial: 'title', locals: { answer: @answer }, formats: [:html]) } }.to_json, status: :ok) else - @notice = failure_message(@note, _("save")) + @notice = failure_message(@note, _('save')) render json: { - "msg" => @notice + 'msg' => @notice }.to_json, status: :bad_request end end @@ -131,27 +129,27 @@ def archive question_id = @note.answer.question_id.to_s if @note.update(note_params) - @notice = success_message(@note, _("removed")) + @notice = success_message(@note, _('removed')) render(json: { - "notes" => { - "id" => question_id, - "html" => render_to_string(partial: "layout", locals: { + 'notes' => { + 'id' => question_id, + 'html' => render_to_string(partial: 'layout', locals: { plan: @plan, question: @question, answer: @answer }, formats: [:html]) }, - "title" => { - "id" => question_id, - "html" => render_to_string(partial: "title", locals: { + 'title' => { + 'id' => question_id, + 'html' => render_to_string(partial: 'title', locals: { answer: @answer }, formats: [:html]) } }.to_json, status: :ok) else - @notice = failure_message(@note, _("remove")) + @notice = failure_message(@note, _('remove')) render json: { - "msg" => @notice + 'msg' => @notice }.to_json, status: :bad_request end end @@ -164,5 +162,4 @@ def note_params .permit(:text, :archived_by, :user_id, :answer_id, :plan_id, :question_id) end - end diff --git a/app/controllers/org_admin/conditions_controller.rb b/app/controllers/org_admin/conditions_controller.rb index 8c2c59376d..552ade2114 100644 --- a/app/controllers/org_admin/conditions_controller.rb +++ b/app/controllers/org_admin/conditions_controller.rb @@ -1,35 +1,36 @@ # frozen_string_literal: true -class OrgAdmin::ConditionsController < ApplicationController +module OrgAdmin + # Controller that handles conditional questions + class ConditionsController < ApplicationController + # /org_admin/questions/:question_id/conditions/new + def new + question = Question.find(params[:question_id]) + condition_no = new_condition_params[:condition_no] + next_condition_no = condition_no.to_i + 1 + render json: { add_link: render_to_string(partial: 'add', + formats: :html, + layout: false, + locals: { question: question, + condition_no: next_condition_no }), + attachment_partial: render_to_string(partial: 'form', + formats: :html, + layout: false, + locals: { + question: question, + cond: Condition.new(question: question), + condition_no: condition_no + }) } + end - # /org_admin/questions/:question_id/conditions/new - def new - question = Question.find(params[:question_id]) - condition_no = new_condition_params[:condition_no] - next_condition_no = condition_no.to_i + 1 - render json: { add_link: render_to_string(partial: "add", - formats: :html, - layout: false, - locals: { question: question, - condition_no: next_condition_no }), - attachment_partial: render_to_string(partial: "form", - formats: :html, - layout: false, - locals: { - question: question, - cond: Condition.new(question: question), - condition_no: condition_no - }) } - end - - private + private - def new_condition_params - params.permit(:condition_no) - end + def new_condition_params + params.permit(:condition_no) + end - def condition_params - params.require(:question_option_id, :action_type).permit(:remove_question_id, :condition_no) + def condition_params + params.require(:question_option_id, :action_type).permit(:remove_question_id, :condition_no) + end end - end diff --git a/app/controllers/org_admin/departments_controller.rb b/app/controllers/org_admin/departments_controller.rb index 8d52cf9293..8613a484c6 100644 --- a/app/controllers/org_admin/departments_controller.rb +++ b/app/controllers/org_admin/departments_controller.rb @@ -1,80 +1,83 @@ # frozen_string_literal: true -class OrgAdmin::DepartmentsController < ApplicationController +module OrgAdmin + # Controller that handles department operations + class DepartmentsController < ApplicationController + after_action :verify_authorized + respond_to :html - after_action :verify_authorized - respond_to :html - - # GET add new department - def new - @department = Department.new - @org_id = org_id - @department.org_id = @org_id - authorize @department - end + # GET add new department + def new + @department = Department.new + @org_id = org_id + @department.org_id = @org_id + authorize @department + end - # POST /departments - # POST /departments.json - def create - @department = Department.new(department_params) - @org_id = org_id + # POST /departments + # POST /departments.json + def create + @department = Department.new(department_params) + @org_id = org_id - authorize @department + authorize @department - if @department.save - flash.now[:notice] = success_message(@department, _("created")) - # reset value - @department = nil - else - flash.now[:alert] = failure_message(@department, _("create")) + if @department.save + flash.now[:notice] = success_message(@department, _('created')) + # reset value + @department = nil + else + flash.now[:alert] = failure_message(@department, _('create')) + end + render :new end - render :new - end - # GET /departments/1/edit - def edit - @department = Department.find(params[:id]) - @org_id = org_id - authorize @department - end + # GET /departments/1/edit + def edit + @department = Department.find(params[:id]) + @org_id = org_id + authorize @department + end - # PUT /departments/1 - def update - @department = Department.find(params[:id]) - @org_id = org_id - authorize @department + # PUT /departments/1 + # rubocop:disable Metrics/AbcSize + def update + @department = Department.find(params[:id]) + @org_id = org_id + authorize @department - if @department.update(department_params) - flash.now[:notice] = success_message(@department, _("saved")) - else - flash.now[:alert] = failure_message(@department, _("save")) + if @department.update(department_params) + flash.now[:notice] = success_message(@department, _('saved')) + else + flash.now[:alert] = failure_message(@department, _('save')) + end + render :edit end - render :edit - end + # rubocop:enable Metrics/AbcSize - # DELETE /departments/1 - def destroy - @department = Department.find(params[:id]) - @org_id = org_id - authorize @department - url = "#{admin_edit_org_path(@org_id)}\#departments" + # DELETE /departments/1 + def destroy + @department = Department.find(params[:id]) + @org_id = org_id + authorize @department + url = "#{admin_edit_org_path(@org_id)}\#departments" - if @department.destroy - flash[:notice] = success_message(@department, _("deleted")) - else - flash[:alert] = failure_message(@department, _("delete")) + if @department.destroy + flash[:notice] = success_message(@department, _('deleted')) + else + flash[:alert] = failure_message(@department, _('delete')) + end + redirect_to url end - redirect_to url - end - private + private - def department_params - params.require(:department).permit(:id, :name, :code, :org_id) - end + def department_params + params.require(:department).permit(:id, :name, :code, :org_id) + end - def org_id - current_user.can_super_admin? ? params[:org_id] : current_user.org_id + def org_id + current_user.can_super_admin? ? params[:org_id] : current_user.org_id + end end - end diff --git a/app/controllers/org_admin/phase_versions_controller.rb b/app/controllers/org_admin/phase_versions_controller.rb index c132c6c294..1d8ae32444 100644 --- a/app/controllers/org_admin/phase_versions_controller.rb +++ b/app/controllers/org_admin/phase_versions_controller.rb @@ -1,20 +1,21 @@ # frozen_string_literal: true -class OrgAdmin::PhaseVersionsController < ApplicationController +module OrgAdmin + # Controller that handles creating new versions of Phases + class PhaseVersionsController < ApplicationController + include Versionable - include Versionable - - # POST /org_admin/templates/:template_id/phases/:phase_id/versions - def create - @phase = Phase.find(params[:phase_id]) - authorize @phase, :create? - @new_phase = get_modifiable(@phase) - flash[:notice] = if @new_phase == @phase - "This template is already a draft" - else - "New version of Template created" - end - redirect_to org_admin_template_phase_url(@new_phase.template, @new_phase) + # POST /org_admin/templates/:template_id/phases/:phase_id/versions + def create + @phase = Phase.find(params[:phase_id]) + authorize @phase, :create? + @new_phase = get_modifiable(@phase) + flash[:notice] = if @new_phase == @phase + 'This template is already a draft' + else + 'New version of Template created' + end + redirect_to org_admin_template_phase_url(@new_phase.template, @new_phase) + end end - end diff --git a/app/controllers/org_admin/phases_controller.rb b/app/controllers/org_admin/phases_controller.rb index 3ef617119a..f27a3e7380 100644 --- a/app/controllers/org_admin/phases_controller.rb +++ b/app/controllers/org_admin/phases_controller.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true module OrgAdmin - + # Controller that handles phases class PhasesController < ApplicationController - include Versionable after_action :verify_authorized @@ -15,7 +14,7 @@ def show authorize phase unless phase.template.latest? # rubocop:disable Layout/LineLength - flash[:notice] = _("You are viewing a historical version of this template. You will not be able to make changes.") + flash[:notice] = _('You are viewing a historical version of this template. You will not be able to make changes.') # rubocop:enable Layout/LineLength end sections = if phase.template.customization_of? && phase.template.latest? @@ -26,9 +25,9 @@ def show # will be readonly phase.sections.order(:number) end - render("container", + render('container', locals: { - partial_path: "show", + partial_path: 'show', template: phase.template, phase: phase, prefix_section: phase.prefix_section, @@ -40,7 +39,7 @@ def show # rubocop:enable Metrics/AbcSize # GET /org_admin/templates/:template_id/phases/:id/edit - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def edit phase = Phase.includes(:template).find(params[:id]) authorize phase @@ -52,9 +51,9 @@ def edit section: params[:section] ) else - render("container", + render('container', locals: { - partial_path: "edit", + partial_path: 'edit', template: phase.template, phase: phase, prefix_section: phase.prefix_section, @@ -65,7 +64,7 @@ def edit }) end end - # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength # preview a phase # GET /org_admin/templates/:template_id/phases/:id/preview @@ -78,6 +77,7 @@ def preview # add a new phase to a passed template # GET /org_admin/templates/:template_id/phases/new + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def new template = Template.includes(:phases).find(params[:template_id]) if template.latest? @@ -93,22 +93,23 @@ def new else org_admin_templates_path end - render("/org_admin/templates/container", + render('/org_admin/templates/container', locals: { - partial_path: "new", + partial_path: 'new', template: template, phase: phase, referrer: local_referrer }) else render org_admin_templates_path, - alert: _("You cannot add a phase to a historical version of a template.") + alert: _('You cannot add a phase to a historical version of a template.') end end + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength # create a phase # POST /org_admin/templates/:template_id/phases - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def create phase = Phase.new(phase_params) phase.template = Template.find(params[:template_id]) @@ -117,12 +118,13 @@ def create phase = get_new(phase) phase.modifiable = true if phase.save - flash[:notice] = success_message(phase, _("created")) + flash[:notice] = success_message(phase, _('created')) else - flash[:alert] = failure_message(phase, _("create")) + flash[:alert] = failure_message(phase, _('create')) end rescue StandardError => e - flash[:alert] = _("Unable to create a new version of this template.") + "
    " + e.message + msg = _('Unable to create a new version of this template.
    ') + flash[:alert] = "#{msg}
    #{e.message}" end if flash[:alert].present? redirect_to new_org_admin_template_phase_path(template_id: phase.template.id) @@ -131,26 +133,29 @@ def create id: phase.id) end end - # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength # update a phase of a template # PUT /org_admin/templates/:template_id/phases/:id + # rubocop:disable Metrics/AbcSize def update phase = Phase.find(params[:id]) authorize phase begin phase = get_modifiable(phase) if phase.update(phase_params) - flash[:notice] = success_message(phase, _("updated")) + flash[:notice] = success_message(phase, _('updated')) else - flash[:alert] = failure_message(phase, _("update")) + flash[:alert] = failure_message(phase, _('update')) end rescue StandardError => e - flash[:alert] = _("Unable to create a new version of this template.") + "
    " + e.message + msg = _('Unable to create a new version of this template.') + flash[:alert] = "#{msg}
    #{e.message}" end redirect_to edit_org_admin_template_phase_path(template_id: phase.template.id, id: phase.id) end + # rubocop:enable Metrics/AbcSize # POST /org_admin/templates/:template_id/phases/:id/sort def sort @@ -171,12 +176,13 @@ def destroy phase = get_modifiable(phase) template = phase.template if phase.destroy! - flash[:notice] = success_message(phase, _("deleted")) + flash[:notice] = success_message(phase, _('deleted')) else - flash[:alert] = failure_message(phase, _("delete")) + flash[:alert] = failure_message(phase, _('delete')) end rescue StandardError => e - flash[:alert] = _("Unable to create a new version of this template.") + "
    " + e.message + msg = _('Unable to create a new version of this template.') + flash[:alert] = "#{msg}
    #{e.message}" end if flash[:alert].present? @@ -192,7 +198,5 @@ def destroy def phase_params params.require(:phase).permit(:title, :description, :number, sort_order: []) end - end - end diff --git a/app/controllers/org_admin/plans_controller.rb b/app/controllers/org_admin/plans_controller.rb index d04739b5fc..81749e0439 100644 --- a/app/controllers/org_admin/plans_controller.rb +++ b/app/controllers/org_admin/plans_controller.rb @@ -1,83 +1,86 @@ # frozen_string_literal: true -class OrgAdmin::PlansController < ApplicationController +module OrgAdmin + # Controller that handles admin operations for plans + class PlansController < ApplicationController + # GET org_admin/plans + # rubocop:disable Metrics/AbcSize + def index + # Test auth directly and throw Pundit error sincePundit + # is unaware of namespacing + raise Pundit::NotAuthorizedError unless current_user.present? && current_user.can_org_admin? - # GET org_admin/plans - def index - # Test auth directly and throw Pundit error sincePundit - # is unaware of namespacing - raise Pundit::NotAuthorizedError unless current_user.present? && current_user.can_org_admin? + sql = 'users.org_id = ? AND plans.feedback_requested is TRUE AND roles.active is TRUE' + feedback_ids = Role.creator.joins(:user, :plan) + .where(sql, current_user.org_id).pluck(:plan_id) + @feedback_plans = Plan.where(id: feedback_ids).reject(&:nil?) - sql = "users.org_id = ? AND plans.feedback_requested is TRUE AND roles.active is TRUE" - feedback_ids = Role.creator.joins(:user, :plan) - .where(sql, current_user.org_id).pluck(:plan_id) - @feedback_plans = Plan.where(id: feedback_ids).reject(&:nil?) - - @super_admin = current_user.can_super_admin? - @clicked_through = params[:click_through].present? - @plans = @super_admin ? Plan.all.page(1) : current_user.org.org_admin_plans.page(1) - end + @super_admin = current_user.can_super_admin? + @clicked_through = params[:click_through].present? + @plans = @super_admin ? Plan.all.page(1) : current_user.org.org_admin_plans.page(1) + end + # rubocop:enable Metrics/AbcSize - # GET org_admin/plans/:id/feedback_complete - def feedback_complete - plan = Plan.find(params[:id]) - # Test auth directly and throw Pundit error sincePundit is - # unaware of namespacing - raise Pundit::NotAuthorizedError unless current_user.present? && current_user.can_org_admin? - raise Pundit::NotAuthorizedError unless plan.reviewable_by?(current_user.id) + # GET org_admin/plans/:id/feedback_complete + # rubocop:disable Metrics/AbcSize + def feedback_complete + plan = Plan.find(params[:id]) + # Test auth directly and throw Pundit error sincePundit is + # unaware of namespacing + raise Pundit::NotAuthorizedError unless current_user.present? && current_user.can_org_admin? + raise Pundit::NotAuthorizedError unless plan.reviewable_by?(current_user.id) - if plan.complete_feedback(current_user) - # rubocop:disable Layout/LineLength - redirect_to(org_admin_plans_path, - notice: _("%{plan_owner} has been notified that you have finished providing feedback") % { - plan_owner: plan.owner.name(false) - }) - # rubocop:enable Layout/LineLength - else - redirect_to org_admin_plans_path, - alert: _("Unable to notify user that you have finished providing feedback.") + if plan.complete_feedback(current_user) + # rubocop:disable Layout/LineLength + redirect_to(org_admin_plans_path, + notice: format(_('%s has been notified that you have finished providing feedback'), plan_owner: plan.owner.name(false))) + # rubocop:enable Layout/LineLength + else + redirect_to org_admin_plans_path, + alert: _('Unable to notify user that you have finished providing feedback.') + end end - end + # rubocop:enable Metrics/AbcSize - # GET /org_admin/download_plans - # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - def download_plans - # Test auth directly and throw Pundit error sincePundit - # is unaware of namespacing - raise Pundit::NotAuthorizedError unless current_user.present? && current_user.can_org_admin? + # GET /org_admin/download_plans + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + def download_plans + # Test auth directly and throw Pundit error sincePundit + # is unaware of namespacing + raise Pundit::NotAuthorizedError unless current_user.present? && current_user.can_org_admin? - org = current_user.org - file_name = org.name.gsub(/ /, "_") - .gsub(/[.;,]/, "") - header_cols = [ - _("Project title").to_s, - _("Template").to_s, - _("Organisation").to_s, - _("Owner name").to_s, - _("Owner email").to_s, - _("Updated").to_s, - _("Visibility").to_s - ] + org = current_user.org + file_name = org.name.gsub(/ /, '_') + .gsub(/[.;,]/, '') + header_cols = [ + _('Project title').to_s, + _('Template').to_s, + _('Organisation').to_s, + _('Owner name').to_s, + _('Owner email').to_s, + _('Updated').to_s, + _('Visibility').to_s + ] - plans = CSV.generate do |csv| - csv << header_cols - org.org_admin_plans.includes(template: :org).order(updated_at: :desc).each do |plan| - csv << [ - plan.title.to_s, - plan.template.title.to_s, - (plan.owner.org.present? ? plan.owner.org.name : "").to_s, - plan.owner.name(false).to_s, - plan.owner.email.to_s, - l(plan.latest_update.to_date, format: :csv).to_s, - Plan::VISIBILITY_MESSAGE[plan.visibility.to_sym].capitalize.to_s - ] + plans = CSV.generate do |csv| + csv << header_cols + org.org_admin_plans.includes(template: :org).order(updated_at: :desc).each do |plan| + csv << [ + plan.title.to_s, + plan.template.title.to_s, + (plan.owner.org.present? ? plan.owner.org.name : '').to_s, + plan.owner.name(false).to_s, + plan.owner.email.to_s, + l(plan.latest_update.to_date, format: :csv).to_s, + Plan::VISIBILITY_MESSAGE[plan.visibility.to_sym].capitalize.to_s + ] + end end - end - respond_to do |format| - format.csv { send_data plans, filename: "#{file_name}.csv" } + respond_to do |format| + format.csv { send_data plans, filename: "#{file_name}.csv" } + end end + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength end - # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - end diff --git a/app/controllers/org_admin/question_options_controller.rb b/app/controllers/org_admin/question_options_controller.rb index 1a5e1948ae..0bdfc7e8d2 100644 --- a/app/controllers/org_admin/question_options_controller.rb +++ b/app/controllers/org_admin/question_options_controller.rb @@ -1,14 +1,13 @@ # frozen_string_literal: true module OrgAdmin - + # Controller that handles question options class QuestionOptionsController < ApplicationController - include Versionable after_action :verify_authorized - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def destroy question_option = QuestionOption.find(params[:id]) option_id_to_remove = question_option.id.to_s @@ -22,12 +21,12 @@ def destroy question.conditions.each do |cond| cond.destroy if cond.option_list.include?(option_id_to_remove) end - flash[:notice] = success_message(question_option, _("deleted")) + flash[:notice] = success_message(question_option, _('deleted')) else - flash[:alert] = flash[:alert] = failure_message(question_option, _("delete")) + flash[:alert] = flash[:alert] = failure_message(question_option, _('delete')) end rescue StandardError - flash[:alert] = _("Unable to create a new version of this template.") + flash[:alert] = _('Unable to create a new version of this template.') end redirect_to edit_org_admin_template_phase_path( template_id: section.phase.template.id, @@ -35,8 +34,6 @@ def destroy section: section.id ) end - # rubocop:enable Metrics/AbcSize - + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength end - end diff --git a/app/controllers/org_admin/questions_controller.rb b/app/controllers/org_admin/questions_controller.rb index f3061c764e..1b19d53074 100644 --- a/app/controllers/org_admin/questions_controller.rb +++ b/app/controllers/org_admin/questions_controller.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true module OrgAdmin - + # Controller that handles questions class QuestionsController < ApplicationController - include AllowedQuestionFormats include Versionable include ConditionsHelper @@ -18,7 +17,7 @@ def show section: { phase: :template }) .find(params[:id]) authorize question - render json: { html: render_to_string(partial: "show", locals: { + render json: { html: render_to_string(partial: 'show', locals: { template: question.section.phase.template, section: question.section, question: question, @@ -31,7 +30,7 @@ def show def open_conditions question = Question.find(params[:question_id]) authorize question - render json: { container: render_to_string(partial: "org_admin/conditions/container", + render json: { container: render_to_string(partial: 'org_admin/conditions/container', formats: :html, layout: false, locals: { @@ -41,16 +40,14 @@ def open_conditions webhooks: webhook_hash(question.conditions) } end - # rubocop:disable Layout/LineLength # GET /org_admin/templates/[:template_id]/phases/[:phase_id]/sections/[:id]/questions/[:question_id]/edit - # rubocop:enable Layout/LineLength def edit question = Question.includes(:annotations, :question_options, section: { phase: :template }) .find(params[:id]) authorize question - render json: { html: render_to_string(partial: "edit", locals: { + render json: { html: render_to_string(partial: 'edit', locals: { template: question.section.phase.template, section: question.section, question: question, @@ -60,20 +57,21 @@ def edit end # GET /org_admin/templates/:template_id/phases/:phase_id/sections/:section_id/questions/new + # rubocop:disable Metrics/AbcSize def new section = Section.includes(:questions, phase: :template).find(params[:section_id]) nbr = section.questions.maximum(:number) - question_format = QuestionFormat.find_by(title: "Text area") + question_format = QuestionFormat.find_by(title: 'Text area') question = Question.new(section_id: section.id, question_format: question_format, number: nbr.present? ? nbr + 1 : 1) question_formats = allowed_question_formats authorize question - render json: { html: render_to_string(partial: "form", locals: { + render json: { html: render_to_string(partial: 'form', locals: { template: section.phase.template, section: section, question: question, - method: "post", + method: 'post', url: org_admin_template_phase_section_questions_path( template_id: section.phase.template.id, phase_id: section.phase.id, @@ -82,6 +80,7 @@ def new question_formats: question_formats }) } end + # rubocop:enable Metrics/AbcSize # POST /org_admin/templates/:template_id/phases/:phase_id/sections/:section_id/questions # rubocop:disable Metrics/AbcSize @@ -92,12 +91,12 @@ def create question = get_new(question) section = question.section if question.save - flash[:notice] = success_message(question, _("created")) + flash[:notice] = success_message(question, _('created')) else - flash[:alert] = failure_message(question, _("create")) + flash[:alert] = failure_message(question, _('create')) end rescue StandardError - flash[:alert] = _("Unable to create a new version of this template.") + flash[:alert] = _('Unable to create a new version of this template.') end redirect_to edit_org_admin_template_phase_path( template_id: section.phase.template.id, @@ -109,6 +108,7 @@ def create # PUT /org_admin/templates/:template_id/phases/:phase_id/sections/:section_id/questions/:id # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def update question = Question.find(params[:id]) authorize question @@ -161,12 +161,12 @@ def update # add check for number present to ensure this is not just an annotation attrs[:theme_ids] = [] if attrs[:theme_ids].blank? && attrs[:number].present? if question.update(attrs) - if question.update_conditions(sanitize_hash(params["conditions"]), + if question.update_conditions(sanitize_hash(params['conditions']), old_to_new_opts, question_id_map) - flash[:notice] = success_message(question, _("updated")) + flash[:notice] = success_message(question, _('updated')) end else - flash[:alert] = flash[:alert] = failure_message(question, _("update")) + flash[:alert] = flash[:alert] = failure_message(question, _('update')) end if question.section.phase.template.customization_of.present? redirect_to org_admin_template_phase_path( @@ -183,7 +183,7 @@ def update end end # rubocop:enable Metrics/AbcSize, Metrics/MethodLength - # rubocop:enable + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity # DELETE /org_admin/templates/:template_id/phases/:phase_id/sections/:section_id/questions/:id # rubocop:disable Metrics/AbcSize @@ -194,12 +194,12 @@ def destroy question = get_modifiable(question) section = question.section if question.destroy! - flash[:notice] = success_message(question, _("deleted")) + flash[:notice] = success_message(question, _('deleted')) else - flash[:alert] = flash[:alert] = failure_message(question, _("delete")) + flash[:alert] = flash[:alert] = failure_message(question, _('delete')) end rescue StandardError - flash[:alert] = _("Unable to create a new version of this template.") + flash[:alert] = _('Unable to create a new version of this template.') end redirect_to edit_org_admin_template_phase_path( template_id: section.phase.template.id, @@ -231,7 +231,7 @@ def sanitize_hash(param_conditions) hash_of_hashes.each do |cond_name, cond_hash| sanitized_hash = {} cond_hash.each do |k, v| - v = ActionController::Base.helpers.sanitize(v) if k.start_with?("webhook") + v = ActionController::Base.helpers.sanitize(v) if k.start_with?('webhook') sanitized_hash[k] = v end res[cond_name] = sanitized_hash @@ -256,11 +256,11 @@ def question_params # options are now out of sync with the params. # This sorts that out. def update_option_ids(attrs_in, opt_map) - qopts = attrs_in["question_options_attributes"] + qopts = attrs_in['question_options_attributes'] qopts.each_pair do |_, attr_hash| - old_id = attr_hash["id"] + old_id = attr_hash['id'] new_id = opt_map[old_id] - attr_hash["id"] = new_id + attr_hash['id'] = new_id end attrs_in end @@ -268,6 +268,7 @@ def update_option_ids(attrs_in, opt_map) # When a template gets versioned by changes to one of its questions we need to loop # through the incoming params and ensure that the annotations and question_options # get attached to the new question + # rubocop:disable Metrics/AbcSize def transfer_associations(attrs, question) if attrs[:annotations_attributes].present? attrs[:annotations_attributes].each_pair do |_, value| @@ -280,7 +281,6 @@ def transfer_associations(attrs, question) end attrs end - + # rubocop:enable Metrics/AbcSize end - end diff --git a/app/controllers/org_admin/sections_controller.rb b/app/controllers/org_admin/sections_controller.rb index 0d5b9b2b2f..2b8c74a698 100644 --- a/app/controllers/org_admin/sections_controller.rb +++ b/app/controllers/org_admin/sections_controller.rb @@ -1,22 +1,22 @@ # frozen_string_literal: true module OrgAdmin - + # Controller that handles sections class SectionsController < ApplicationController - include Versionable respond_to :html after_action :verify_authorized # GET /org_admin/templates/[:template_id]/phases/[:phase_id]/sections + # rubocop:disable Metrics/AbcSize def index authorize Section.new phase = Phase.includes(:template, :sections).find(params[:phase_id]) edit = phase.template.latest? && (current_user.can_modify_templates? && (phase.template.org_id == current_user.org_id)) - render partial: "index", + render partial: 'index', locals: { template: phase.template, phase: phase, @@ -28,6 +28,7 @@ def index edit: edit } end + # rubocop:enable Metrics/AbcSize # GET /org_admin/templates/[:template_id]/phases/[:phase_id]/sections/[:id] def show @@ -36,7 +37,7 @@ def show @section = Section.includes(questions: %i[annotations question_options]) .find(params[:id]) @template = Template.find(params[:template_id]) - render json: { html: render_to_string(partial: "show", + render json: { html: render_to_string(partial: 'show', locals: { template: @template, section: @section }) } end @@ -49,9 +50,9 @@ def edit # User cannot edit a section if its not modifiable or the template is not the # latest redirect to show partial_name = if section.modifiable? && section.phase.template.latest? - "edit" + 'edit' else - "show" + 'show' end render json: { html: render_to_string(partial: partial_name, locals: { @@ -62,12 +63,12 @@ def edit end # POST /org_admin/templates/[:template_id]/phases/[:phase_id]/sections - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def create @phase = Phase.find_by(id: params[:phase_id]) if @phase.nil? flash[:alert] = - _("Unable to create a new section. The phase you specified does not exist.") + _('Unable to create a new section. The phase you specified does not exist.') redirect_to edit_org_admin_template_path(template_id: params[:template_id]) return end @@ -75,21 +76,21 @@ def create authorize @section @section = get_new(@section) if @section.save - flash[:notice] = success_message(@section, _("created")) + flash[:notice] = success_message(@section, _('created')) redirect_to edit_org_admin_template_phase_path( id: @section.phase_id, template_id: @phase.template_id, section: @section.id ) else - flash[:alert] = failure_message(@section, _("create")) + flash[:alert] = failure_message(@section, _('create')) redirect_to edit_org_admin_template_phase_path( template_id: @phase.template_id, id: @section.phase_id ) end end - # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength # PUT /org_admin/templates/[:template_id]/phases/[:phase_id]/sections/[:id] # rubocop:disable Metrics/AbcSize @@ -99,12 +100,13 @@ def update begin section = get_modifiable(section) if section.update(section_params) - flash[:notice] = success_message(section, _("saved")) + flash[:notice] = success_message(section, _('saved')) else - flash[:alert] = failure_message(section, _("save")) + flash[:alert] = failure_message(section, _('save')) end rescue StandardError => e - flash[:alert] = _("Unable to create a new version of this template.") + "
    " + e.message + msg = _('Unable to create a new version of this template.') + flash[:alert] = "#{msg}
    #{e.message}" end redirect_to edit_org_admin_template_phase_path( @@ -123,12 +125,13 @@ def destroy section = get_modifiable(section) phase = section.phase if section.destroy! - flash[:notice] = success_message(section, _("deleted")) + flash[:notice] = success_message(section, _('deleted')) else - flash[:alert] = failure_message(section, _("delete")) + flash[:alert] = failure_message(section, _('delete')) end rescue StandardError => e - flash[:alert] = _("Unable to create a new version of this template.") + "
    " + e.message + msg = _('Unable to delete this version of the template.') + flash[:alert] = "#{msg}
    #{e.message}" end redirect_to(edit_org_admin_template_phase_path( @@ -143,7 +146,5 @@ def destroy def section_params params.require(:section).permit(:title, :description) end - end - end diff --git a/app/controllers/org_admin/template_copies_controller.rb b/app/controllers/org_admin/template_copies_controller.rb index db65f414bb..6e3c99af85 100644 --- a/app/controllers/org_admin/template_copies_controller.rb +++ b/app/controllers/org_admin/template_copies_controller.rb @@ -1,27 +1,30 @@ # frozen_string_literal: true -class OrgAdmin::TemplateCopiesController < ApplicationController +module OrgAdmin + # Controller that handles copying templates + class TemplateCopiesController < ApplicationController + include TemplateMethods - include TemplateMethods + after_action :verify_authorized - after_action :verify_authorized - - # POST /org_admin/templates/:id/copy (AJAX) - def create - @template = Template.find(params[:template_id]) - authorize @template, :copy? - begin - new_copy = @template.generate_copy!(current_user.org) - flash[:notice] = "#{template_type(@template).capitalize} was successfully copied." - redirect_to edit_org_admin_template_path(new_copy) - rescue StandardError - flash[:alert] = failure_message(_("copy"), template_type(@template)) - if request.referrer.present? - redirect_back(fallback_location: org_admin_templates_path) - else - redirect_to org_admin_templates_path + # POST /org_admin/templates/:id/copy (AJAX) + # rubocop:disable Metrics/AbcSize + def create + @template = Template.find(params[:template_id]) + authorize @template, :copy? + begin + new_copy = @template.generate_copy!(current_user.org) + flash[:notice] = "#{template_type(@template).capitalize} was successfully copied." + redirect_to edit_org_admin_template_path(new_copy) + rescue StandardError + flash[:alert] = failure_message(_('copy'), template_type(@template)) + if request.referrer.present? + redirect_back(fallback_location: org_admin_templates_path) + else + redirect_to org_admin_templates_path + end end end + # rubocop:enable Metrics/AbcSize end - end diff --git a/app/controllers/org_admin/template_customization_transfers_controller.rb b/app/controllers/org_admin/template_customization_transfers_controller.rb index 5268b2bcf0..f0b98e28b7 100644 --- a/app/controllers/org_admin/template_customization_transfers_controller.rb +++ b/app/controllers/org_admin/template_customization_transfers_controller.rb @@ -1,32 +1,33 @@ # frozen_string_literal: true -class OrgAdmin::TemplateCustomizationTransfersController < ApplicationController - - include Versionable - - after_action :verify_authorized - - # POST /org_admin/templates/:id/transfer_customization - # - # The funder template's id is passed through here - def create - @template = Template.find(params[:template_id]) - authorize @template, :transfer_customization? - if @template.upgrade_customization? - # If the customized template is not published it will not version, so publish it! - previously_published = @template.published? - @template.publish unless previously_published - - @new_customization = @template.upgrade_customization! - - # Reset the published flag if the customized template was not previously published - @template.update(published: false) unless previously_published - - redirect_to org_admin_template_path(@new_customization) - else - flash[:alert] = _("That template is no longer customizable.") - redirect_back(fallback_location: org_admin_templates_path) +module OrgAdmin + # Controller that handles transfering parent template changes to a customized template + class TemplateCustomizationTransfersController < ApplicationController + include Versionable + + after_action :verify_authorized + + # POST /org_admin/templates/:id/transfer_customization + # + # The funder template's id is passed through here + def create + @template = Template.find(params[:template_id]) + authorize @template, :transfer_customization? + if @template.upgrade_customization? + # If the customized template is not published it will not version, so publish it! + previously_published = @template.published? + @template.publish unless previously_published + + @new_customization = @template.upgrade_customization! + + # Reset the published flag if the customized template was not previously published + @template.update(published: false) unless previously_published + + redirect_to org_admin_template_path(@new_customization) + else + flash[:alert] = _('That template is no longer customizable.') + redirect_back(fallback_location: org_admin_templates_path) + end end end - end diff --git a/app/controllers/org_admin/template_customizations_controller.rb b/app/controllers/org_admin/template_customizations_controller.rb index 91094a5ead..15c37f533b 100644 --- a/app/controllers/org_admin/template_customizations_controller.rb +++ b/app/controllers/org_admin/template_customizations_controller.rb @@ -1,27 +1,30 @@ # frozen_string_literal: true -class OrgAdmin::TemplateCustomizationsController < ApplicationController +module OrgAdmin + # Controller that handles customizing a template + class TemplateCustomizationsController < ApplicationController + include Paginable + include Versionable + after_action :verify_authorized - include Paginable - include Versionable - after_action :verify_authorized - - # POST /org_admin/templates/:id/customize - def create - @template = Template.find(params[:template_id]) - authorize(@template, :customize?) - if @template.customize?(current_user.org) - begin - @customisation = @template.customize!(current_user.org) - redirect_to org_admin_template_path(@customisation) - return - rescue ArgumentError - flash[:alert] = _("Unable to customize that template.") + # POST /org_admin/templates/:id/customize + # rubocop:disable Metrics/AbcSize + def create + @template = Template.find(params[:template_id]) + authorize(@template, :customize?) + if @template.customize?(current_user.org) + begin + @customisation = @template.customize!(current_user.org) + redirect_to org_admin_template_path(@customisation) + return + rescue ArgumentError + flash[:alert] = _('Unable to customize that template.') + end + else + flash[:notice] = _('That template is not customizable.') end - else - flash[:notice] = _("That template is not customizable.") + redirect_back(fallback_location: org_admin_templates_path) end - redirect_back(fallback_location: org_admin_templates_path) + # rubocop:enable Metrics/AbcSize end - end diff --git a/app/controllers/org_admin/templates_controller.rb b/app/controllers/org_admin/templates_controller.rb index 3f26367365..1cc4c48d58 100644 --- a/app/controllers/org_admin/templates_controller.rb +++ b/app/controllers/org_admin/templates_controller.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true module OrgAdmin - - # rubocop:disable Metrics/ClassLength + # Controller that handles templates class TemplatesController < ApplicationController - include Paginable include Versionable include TemplateMethods @@ -13,16 +11,16 @@ class TemplatesController < ApplicationController # The root version of index which returns all templates # GET /org_admin/templates - # ----------------------------------------------------- + # rubocop:disable Metrics/AbcSize def index authorize Template templates = Template.latest_version.where(customization_of: nil) published = templates.select { |t| t.published? || t.draft? }.length @orgs = Org.managed - @title = _("All Templates") + @title = _('All Templates') @templates = templates.includes(:org).page(1) - @query_params = { sort_field: "templates.title", sort_direction: "asc" } + @query_params = { sort_field: 'templates.title', sort_direction: 'asc' } @all_count = templates.length @published_count = published.present? ? published : 0 @unpublished_count = if published.present? @@ -32,11 +30,12 @@ def index end render :index end + # rubocop:enable Metrics/AbcSize # A version of index that displays only templates that belong to the user's org # GET /org_admin/templates/organisational # ----------------------------------------------------- - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity def organisational authorize Template templates = Template.latest_version_per_org(current_user.org.id) @@ -45,12 +44,12 @@ def organisational @orgs = current_user.can_super_admin? ? Org.all : nil @title = if current_user.can_super_admin? - _("%{org_name} Templates") % { org_name: current_user.org.name } + format(_('%s Templates'), org_name: current_user.org.name) else - _("Own Templates") + _('Own Templates') end @templates = templates.page(1) - @query_params = { sort_field: "templates.title", sort_direction: "asc" } + @query_params = { sort_field: 'templates.title', sort_direction: 'asc' } @all_count = templates.length @published_count = published.present? ? published : 0 @unpublished_count = if published.present? @@ -60,12 +59,13 @@ def organisational end render :index end - # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity # A version of index that displays only templates that are customizable # GET /org_admin/templates/customisable # ----------------------------------------------------- - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def customisable authorize Template customizations = Template.latest_customized_version_per_org(current_user.org.id) @@ -81,10 +81,10 @@ def customisable published = customizations.select { |t| t.published? || t.draft? }.length @orgs = current_user.can_super_admin? ? Org.all : [] - @title = _("Customizable Templates") + @title = _('Customizable Templates') @templates = funder_templates @customizations = customizations - @query_params = { sort_field: "templates.title", sort_direction: "asc" } + @query_params = { sort_field: 'templates.title', sort_direction: 'asc' } @all_count = funder_templates.length @published_count = published.present? ? published : 0 @unpublished_count = if published.present? @@ -96,7 +96,8 @@ def customisable render :index end - # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity # GET /org_admin/templates/[:id] def show @@ -105,17 +106,17 @@ def show # Load the info needed for the overview section if the authorization check passes! phases = template.phases .includes(sections: { questions: :question_options }) - .order("phases.number", "sections.number", "questions.number", - "question_options.number") - .select("phases.title", "phases.description", "sections.title", - "questions.text", "question_options.text") + .order('phases.number', 'sections.number', 'questions.number', + 'question_options.number') + .select('phases.title', 'phases.description', 'sections.title', + 'questions.text', 'question_options.text') unless template.latest? # rubocop:disable Layout/LineLength - flash[:notice] = _("You are viewing a historical version of this template. You will not be able to make changes.") + flash[:notice] = _('You are viewing a historical version of this template. You will not be able to make changes.') # rubocop:enable Layout/LineLength end - render "container", locals: { - partial_path: "show", + render 'container', locals: { + partial_path: 'show', template: template, phases: phases, referrer: get_referrer(template, request.referrer) @@ -123,31 +124,33 @@ def show end # GET /org_admin/templates/:id/edit + # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def edit template = Template.includes(:org, :phases).find(params[:id]) authorize template # Load the info needed for the overview section if the authorization check passes! phases = template.phases.includes(sections: { questions: :question_options }) - .order("phases.number", - "sections.number", - "questions.number", - "question_options.number") - .select("phases.title", - "phases.description", - "sections.title", - "questions.text", - "question_options.text") - if !template.latest? - redirect_to org_admin_template_path(id: template.id) - else - render "container", locals: { - partial_path: "edit", + .order('phases.number', + 'sections.number', + 'questions.number', + 'question_options.number') + .select('phases.title', + 'phases.description', + 'sections.title', + 'questions.text', + 'question_options.text') + if template.latest? + render 'container', locals: { + partial_path: 'edit', template: template, phases: phases, referrer: get_referrer(template, request.referrer) } + else + redirect_to org_admin_template_path(id: template.id) end end + # rubocop:enable Metrics/AbcSize, Metrics/MethodLength # GET /org_admin/templates/new def new @@ -167,16 +170,16 @@ def create @template = Template.new(args) @template.org_id = current_user.org.id @template.locale = current_org.language.abbreviation - @template.links = if params["template-links"].present? - ActiveSupport::JSON.decode(params["template-links"]) + @template.links = if params['template-links'].present? + ActiveSupport::JSON.decode(params['template-links']) else - { "funder": [], "sample_plan": [] } + { funder: [], sample_plan: [] } end if @template.save redirect_to edit_org_admin_template_path(@template), - notice: success_message(@template, _("created")) + notice: success_message(@template, _('created')) else - flash[:alert] = flash[:alert] = failure_message(@template, _("create")) + flash[:alert] = flash[:alert] = failure_message(@template, _('create')) render :new end end @@ -194,25 +197,23 @@ def update args[:visibility] = parse_visibility(args, current_user.org) template.assign_attributes(args) - if params["template-links"].present? - template.links = ActiveSupport::JSON.decode(params["template-links"]) - end + template.links = ActiveSupport::JSON.decode(params['template-links']) if params['template-links'].present? if template.save render(json: { status: 200, - msg: success_message(template, _("saved")) + msg: success_message(template, _('saved')) }) else render(json: { status: :bad_request, - msg: failure_message(template, _("save")) + msg: failure_message(template, _('save')) }) end rescue ActiveSupport::JSON.parse_error render(json: { status: :bad_request, - msg: _("Error parsing links for a %{template}") % - { template: template_type(template) } + msg: format(_('Error parsing links for a %