diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..9af7d156 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,1176 @@ +AllCops: + Exclude: + - 'db/schema.rb' + DisabledByDefault: true + TargetRubyVersion: 2.5 + +Layout/AccessModifierIndentation: + EnforcedStyle: indent + SupportedStyles: + - outdent + - indent + IndentationWidth: + +Style/Alias: + EnforcedStyle: prefer_alias_method + SupportedStyles: + - prefer_alias + - prefer_alias_method + +Layout/AlignHash: + EnforcedHashRocketStyle: key + EnforcedColonStyle: key + EnforcedLastArgumentHashStyle: ignore_implicit + SupportedLastArgumentHashStyles: + - always_inspect + - always_ignore + - ignore_implicit + - ignore_explicit + +Layout/AlignParameters: + EnforcedStyle: with_fixed_indentation + SupportedStyles: + - with_first_parameter + - with_fixed_indentation + IndentationWidth: + +Style/AndOr: + EnforcedStyle: always + SupportedStyles: + - always + - conditionals + +Style/BarePercentLiterals: + EnforcedStyle: bare_percent + SupportedStyles: + - percent_q + - bare_percent + +Style/BlockDelimiters: + EnforcedStyle: line_count_based + SupportedStyles: + - line_count_based + - semantic + - braces_for_chaining + ProceduralMethods: + - benchmark + - bm + - bmbm + - create + - each_with_object + - measure + - new + - realtime + - tap + - with_object + FunctionalMethods: + - let + - let! + - subject + - watch + IgnoredMethods: + - lambda + - proc + - it + +Style/BracesAroundHashParameters: + EnforcedStyle: no_braces + SupportedStyles: + - braces + - no_braces + - context_dependent + +Layout/CaseIndentation: + EnforcedStyle: end + SupportedStyles: + - case + - end + IndentOneStep: false + IndentationWidth: + +Style/ClassAndModuleChildren: + EnforcedStyle: nested + SupportedStyles: + - nested + - compact + +Style/ClassCheck: + EnforcedStyle: is_a? + SupportedStyles: + - is_a? + - kind_of? + +Style/CommandLiteral: + EnforcedStyle: backticks + SupportedStyles: + - backticks + - percent_x + - mixed + AllowInnerBackticks: false + +Style/CommentAnnotation: + Keywords: + - TODO + - FIXME + - OPTIMIZE + - HACK + - REVIEW + +Style/ConditionalAssignment: + EnforcedStyle: assign_to_condition + SupportedStyles: + - assign_to_condition + - assign_inside_condition + SingleLineConditionsOnly: true + +Layout/DotPosition: + EnforcedStyle: leading + SupportedStyles: + - leading + - trailing + +Style/EmptyElse: + EnforcedStyle: both + SupportedStyles: + - empty + - nil + - both + +Layout/EmptyLineBetweenDefs: + AllowAdjacentOneLineDefs: false + +Layout/EmptyLinesAroundBlockBody: + EnforcedStyle: no_empty_lines + SupportedStyles: + - empty_lines + - no_empty_lines + +Layout/EmptyLinesAroundClassBody: + EnforcedStyle: no_empty_lines + SupportedStyles: + - empty_lines + - empty_lines_except_namespace + - no_empty_lines + +Layout/EmptyLinesAroundModuleBody: + EnforcedStyle: no_empty_lines + SupportedStyles: + - empty_lines + - empty_lines_except_namespace + - no_empty_lines + +Layout/ExtraSpacing: + AllowForAlignment: true + ForceEqualSignAlignment: false + +Naming/FileName: + Exclude: [] + ExpectMatchingDefinition: false + Regex: + IgnoreExecutableScripts: true + +Layout/FirstParameterIndentation: + EnforcedStyle: consistent + SupportedStyles: + - consistent + - special_for_inner_method_call + - special_for_inner_method_call_in_parentheses + IndentationWidth: + +Style/For: + EnforcedStyle: each + SupportedStyles: + - for + - each + +Style/FormatString: + EnforcedStyle: format + SupportedStyles: + - format + - sprintf + - percent + +Style/FrozenStringLiteralComment: + Details: >- + Add `# frozen_string_literal: true` to the top of the file. Frozen string + literals will become the default in a future Ruby version, and we want to + make sure we're ready. + EnforcedStyle: when_needed + SupportedStyles: + - when_needed + - always + - never + +Style/GlobalVars: + AllowedVariables: [] + +Style/HashSyntax: + EnforcedStyle: ruby19 + SupportedStyles: + - ruby19 + - hash_rockets + - no_mixed_keys + - ruby19_no_mixed_keys + UseHashRocketsWithSymbolValues: false + PreferHashRocketsForNonAlnumEndingSymbols: false + +Layout/IndentationConsistency: + EnforcedStyle: normal + SupportedStyles: + - normal + - rails + +Layout/IndentationWidth: + Width: 2 + +Layout/IndentArray: + EnforcedStyle: consistent + SupportedStyles: + - special_inside_parentheses + - consistent + - align_brackets + IndentationWidth: + +Layout/IndentAssignment: + IndentationWidth: + +Layout/IndentHash: + EnforcedStyle: consistent + SupportedStyles: + - special_inside_parentheses + - consistent + - align_braces + IndentationWidth: + +Style/LambdaCall: + EnforcedStyle: call + SupportedStyles: + - call + - braces + +Style/Next: + EnforcedStyle: skip_modifier_ifs + MinBodyLength: 3 + SupportedStyles: + - skip_modifier_ifs + - always + +Style/NonNilCheck: + IncludeSemanticChanges: false + +Style/MethodDefParentheses: + EnforcedStyle: require_parentheses + SupportedStyles: + - require_parentheses + - require_no_parentheses + - require_no_parentheses_except_multiline + +Naming/MethodName: + EnforcedStyle: snake_case + SupportedStyles: + - snake_case + - camelCase + +Layout/MultilineArrayBraceLayout: + EnforcedStyle: symmetrical + SupportedStyles: + - symmetrical + - new_line + - same_line + +Layout/MultilineHashBraceLayout: + EnforcedStyle: symmetrical + SupportedStyles: + - symmetrical + - new_line + - same_line + +Layout/MultilineMethodCallBraceLayout: + EnforcedStyle: symmetrical + SupportedStyles: + - symmetrical + - new_line + - same_line + +Layout/MultilineMethodCallIndentation: + EnforcedStyle: indented + SupportedStyles: + - aligned + - indented + - indented_relative_to_receiver + IndentationWidth: 2 + +Layout/MultilineMethodDefinitionBraceLayout: + EnforcedStyle: symmetrical + SupportedStyles: + - symmetrical + - new_line + - same_line + +Style/NumericLiteralPrefix: + EnforcedOctalStyle: zero_only + SupportedOctalStyles: + - zero_with_o + - zero_only + +Style/ParenthesesAroundCondition: + AllowSafeAssignment: true + +Style/PercentLiteralDelimiters: + PreferredDelimiters: + '%': '()' + '%i': '()' + '%q': '()' + '%Q': '()' + '%r': '{}' + '%s': '()' + '%w': '()' + '%W': '()' + '%x': '()' + +Style/PercentQLiterals: + EnforcedStyle: lower_case_q + SupportedStyles: + - lower_case_q + - upper_case_q + +Naming/PredicateName: + NamePrefix: + - is_ + NamePrefixBlacklist: + - is_ + NameWhitelist: + - is_a? + Exclude: + - 'spec/**/*' + +Style/PreferredHashMethods: + EnforcedStyle: short + SupportedStyles: + - short + - verbose + +Style/RaiseArgs: + EnforcedStyle: exploded + SupportedStyles: + - compact + - exploded + +Style/RedundantReturn: + AllowMultipleReturnValues: false + +Style/RegexpLiteral: + EnforcedStyle: mixed + SupportedStyles: + - slashes + - percent_r + - mixed + AllowInnerSlashes: false + +Style/SafeNavigation: + ConvertCodeThatCanStartToReturnNil: false + Enabled: true + +Lint/SafeNavigationChain: + Enabled: true + +Style/Semicolon: + AllowAsExpressionSeparator: false + +Style/SignalException: + EnforcedStyle: only_raise + SupportedStyles: + - only_raise + - only_fail + - semantic + +Style/SingleLineMethods: + AllowIfMethodIsEmpty: true + +Layout/SpaceBeforeFirstArg: + AllowForAlignment: true + +Style/SpecialGlobalVars: + EnforcedStyle: use_english_names + SupportedStyles: + - use_perl_names + - use_english_names + +Style/StabbyLambdaParentheses: + EnforcedStyle: require_parentheses + SupportedStyles: + - require_parentheses + - require_no_parentheses + +Style/StringLiteralsInInterpolation: + EnforcedStyle: single_quotes + SupportedStyles: + - single_quotes + - double_quotes + +Layout/SpaceAroundBlockParameters: + EnforcedStyleInsidePipes: no_space + SupportedStylesInsidePipes: + - space + - no_space + +Layout/SpaceAroundEqualsInParameterDefault: + EnforcedStyle: space + SupportedStyles: + - space + - no_space + +Layout/SpaceAroundOperators: + AllowForAlignment: true + +Layout/SpaceBeforeBlockBraces: + EnforcedStyle: space + EnforcedStyleForEmptyBraces: space + SupportedStyles: + - space + - no_space + +Layout/SpaceInsideBlockBraces: + EnforcedStyle: space + SupportedStyles: + - space + - no_space + EnforcedStyleForEmptyBraces: no_space + SpaceBeforeBlockParameters: true + +Layout/SpaceInsideHashLiteralBraces: + EnforcedStyle: space + EnforcedStyleForEmptyBraces: no_space + SupportedStyles: + - space + - no_space + - compact + +Layout/SpaceInsideStringInterpolation: + EnforcedStyle: no_space + SupportedStyles: + - space + - no_space + +Style/SymbolProc: + IgnoredMethods: + - respond_to + - define_method + +Style/TernaryParentheses: + EnforcedStyle: require_no_parentheses + SupportedStyles: + - require_parentheses + - require_no_parentheses + AllowSafeAssignment: true + +Layout/TrailingBlankLines: + EnforcedStyle: final_newline + SupportedStyles: + - final_newline + - final_blank_line + +Style/TrivialAccessors: + ExactNameMatch: true + AllowPredicates: true + AllowDSLWriters: false + IgnoreClassMethods: false + Whitelist: + - to_ary + - to_a + - to_c + - to_enum + - to_h + - to_hash + - to_i + - to_int + - to_io + - to_open + - to_path + - to_proc + - to_r + - to_regexp + - to_str + - to_s + - to_sym + +Naming/VariableName: + EnforcedStyle: snake_case + SupportedStyles: + - snake_case + - camelCase + +Style/WhileUntilModifier: + Enabled: true + +Style/WordArray: + EnforcedStyle: percent + SupportedStyles: + - percent + - brackets + MinSize: 0 + WordRegex: !ruby/regexp /\A[\p{Word}\n\t]+\z/ + +Metrics/BlockNesting: + Max: 3 + +Metrics/LineLength: + Max: 120 + AllowHeredoc: true + AllowURI: true + URISchemes: + - http + - https + IgnoreCopDirectives: false + IgnoredPatterns: + - '\A\s*(remote_)?test(_\w+)?\s.*(do|->)(\s|\Z)' + +Metrics/ParameterLists: + Max: 5 + CountKeywordArgs: false + +Layout/BlockAlignment: + EnforcedStyleAlignWith: either + SupportedStylesAlignWith: + - either + - start_of_block + - start_of_line + +Layout/EndAlignment: + EnforcedStyleAlignWith: variable + SupportedStylesAlignWith: + - keyword + - variable + - start_of_line + +Layout/DefEndAlignment: + EnforcedStyleAlignWith: start_of_line + SupportedStylesAlignWith: + - start_of_line + - def + +Lint/InheritException: + EnforcedStyle: runtime_error + SupportedStyles: + - runtime_error + - standard_error + +Lint/UnusedBlockArgument: + IgnoreEmptyBlocks: true + AllowUnusedKeywordArguments: false + +Lint/UnusedMethodArgument: + AllowUnusedKeywordArguments: false + IgnoreEmptyMethods: true + +Performance/RedundantMerge: + MaxKeyValuePairs: 2 + +Rails/ActionFilter: + EnforcedStyle: action + SupportedStyles: + - action + - filter + Include: + - app/controllers/**/*.rb + +Rails/Date: + EnforcedStyle: flexible + SupportedStyles: + - strict + - flexible + +Rails/DynamicFindBy: + Whitelist: + - find_by_sql + +Rails/Exit: + Include: + - app/**/*.rb + - config/**/*.rb + - lib/**/*.rb + Exclude: + - 'lib/**/*.rake' + +Rails/FindBy: + Include: + - app/models/**/*.rb + +Rails/FindEach: + Include: + - app/models/**/*.rb + +Rails/HasAndBelongsToMany: + Include: + - app/models/**/*.rb + +Rails/NotNullColumn: + Include: + - db/migrate/*.rb + +Rails/Output: + Include: + - app/**/*.rb + - config/**/*.rb + - db/**/*.rb + - lib/**/*.rb + +Rails/ReadWriteAttribute: + Include: + - app/models/**/*.rb + +Rails/RequestReferer: + EnforcedStyle: referer + SupportedStyles: + - referer + - referrer + +Rails/SafeNavigation: + ConvertTry: false + +Rails/ScopeArgs: + Include: + - app/models/**/*.rb + +Rails/TimeZone: + EnforcedStyle: flexible + SupportedStyles: + - strict + - flexible + +Rails/UniqBeforePluck: + EnforcedStyle: conservative + SupportedStyles: + - conservative + - aggressive + +Rails/Validation: + Include: + - app/models/**/*.rb + +Naming/AccessorMethodName: + Enabled: true + +Layout/AlignArray: + Enabled: true + +Style/ArrayJoin: + Enabled: true + +Naming/AsciiIdentifiers: + Enabled: true + +Style/Attr: + Enabled: true + +Style/BeginBlock: + Enabled: true + +Style/BlockComments: + Enabled: true + +Layout/BlockEndNewline: + Enabled: true + +Style/CaseEquality: + Enabled: true + +Style/CharacterLiteral: + Enabled: true + +Naming/ClassAndModuleCamelCase: + Enabled: true + +Style/ClassMethods: + Enabled: true + +Style/ClassVars: + Enabled: true + +Layout/ClosingParenthesisIndentation: + Enabled: true + +Style/ColonMethodCall: + Enabled: true + +Layout/CommentIndentation: + Enabled: true + +Naming/ConstantName: + Enabled: true + +Style/DefWithParentheses: + Enabled: true + +Style/EachForSimpleLoop: + Enabled: true + +Style/EachWithObject: + Enabled: true + +Layout/ElseAlignment: + Enabled: true + +Style/EmptyCaseCondition: + Enabled: true + +Layout/EmptyLines: + Enabled: true + +Layout/EmptyLinesAroundAccessModifier: + Enabled: true + +Layout/EmptyLinesAroundMethodBody: + Enabled: true + +Style/EmptyLiteral: + Enabled: true + +Style/EndBlock: + Enabled: true + +Layout/EndOfLine: + Enabled: true + +Style/EvenOdd: + Enabled: true + +Layout/InitialIndentation: + Enabled: true + +Style/FlipFlop: + Enabled: true + +Style/IfInsideElse: + Enabled: true + +Style/IfUnlessModifierOfIfUnless: + Enabled: true + +Style/IfWithSemicolon: + Enabled: true + +Style/IdenticalConditionalBranches: + Enabled: true + +Style/InfiniteLoop: + Enabled: true + +Layout/LeadingCommentSpace: + Enabled: true + +Style/LineEndConcatenation: + Enabled: true + +Style/MethodCallWithoutArgsParentheses: + Enabled: true + +Style/MethodMissingSuper: + Enabled: true + +Style/MissingRespondToMissing: + Enabled: true + +Style/MultilineBlockChain: + Enabled: true + +Layout/MultilineBlockLayout: + Enabled: true + +Style/MultilineIfThen: + Enabled: true + +Style/MultilineMemoization: + Enabled: true + +Style/MultilineTernaryOperator: + Enabled: true + +Style/NegatedIf: + Enabled: true + +Style/NegatedWhile: + Enabled: true + +Style/NestedModifier: + Enabled: true + +Style/NestedParenthesizedCalls: + Enabled: true + +Style/NestedTernaryOperator: + Enabled: true + +Style/NilComparison: + Enabled: true + +Style/Not: + Enabled: true + +Style/OneLineConditional: + Enabled: true + +Naming/BinaryOperatorParameterName: + Enabled: true + +Style/OptionalArguments: + Enabled: true + +Style/ParallelAssignment: + Enabled: true + +Style/PerlBackrefs: + Enabled: true + +Style/Proc: + Enabled: true + +Style/RedundantBegin: + Enabled: true + +Style/RedundantException: + Enabled: true + +Style/RedundantFreeze: + Enabled: true + +Style/RedundantParentheses: + Enabled: true + +Style/RedundantSelf: + Enabled: true + +Layout/RescueEnsureAlignment: + Enabled: true + +Style/RescueModifier: + Enabled: true + +Style/SelfAssignment: + Enabled: true + +Layout/SpaceAfterColon: + Enabled: true + +Layout/SpaceAfterComma: + Enabled: true + +Layout/SpaceAfterMethodName: + Enabled: true + +Layout/SpaceAfterNot: + Enabled: true + +Layout/SpaceAfterSemicolon: + Enabled: true + +Layout/SpaceBeforeComma: + Enabled: true + +Layout/SpaceBeforeComment: + Enabled: true + +Layout/SpaceBeforeSemicolon: + Enabled: true + +Layout/SpaceAroundKeyword: + Enabled: true + +Layout/SpaceInsideArrayPercentLiteral: + Enabled: true + +Layout/SpaceInsidePercentLiteralDelimiters: + Enabled: true + +Layout/SpaceInsideArrayLiteralBrackets: + Enabled: true + +Layout/SpaceInsideParens: + Enabled: true + +Layout/SpaceInsideRangeLiteral: + Enabled: true + +Style/SymbolLiteral: + Enabled: true + +Layout/Tab: + Enabled: true + +Layout/TrailingWhitespace: + Enabled: true + +Style/UnlessElse: + Enabled: true + +Style/UnneededCapitalW: + Enabled: true + +Style/UnneededInterpolation: + Enabled: true + +Style/UnneededPercentQ: + Enabled: true + +Style/VariableInterpolation: + Enabled: true + +Style/WhenThen: + Enabled: true + +Style/WhileUntilDo: + Enabled: true + +Style/ZeroLengthPredicate: + Enabled: true + +Layout/IndentHeredoc: + EnforcedStyle: squiggly + +Lint/AmbiguousOperator: + Enabled: true + +Lint/AmbiguousRegexpLiteral: + Enabled: true + +Lint/CircularArgumentReference: + Enabled: true + +Layout/ConditionPosition: + Enabled: true + +Lint/Debugger: + Enabled: true + +Lint/DeprecatedClassMethods: + Enabled: true + +Lint/DuplicateMethods: + Enabled: true + +Lint/DuplicatedKey: + Enabled: true + +Lint/EachWithObjectArgument: + Enabled: true + +Lint/ElseLayout: + Enabled: true + +Lint/EmptyEnsure: + Enabled: true + +Lint/EmptyInterpolation: + Enabled: true + +Lint/EndInMethod: + Enabled: true + +Lint/EnsureReturn: + Enabled: true + +Lint/FloatOutOfRange: + Enabled: true + +Lint/FormatParameterMismatch: + Enabled: true + +Lint/HandleExceptions: + Enabled: true + +Lint/ImplicitStringConcatenation: + Description: Checks for adjacent string literals on the same line, which could + better be represented as a single string literal. + +Lint/IneffectiveAccessModifier: + Description: Checks for attempts to use `private` or `protected` to set the visibility + of a class method, which does not work. + +Lint/LiteralAsCondition: + Enabled: true + +Lint/LiteralInInterpolation: + Enabled: true + +Lint/Loop: + Description: Use Kernel#loop with break rather than begin/end/until or begin/end/while + for post-loop tests. + +Lint/NestedMethodDefinition: + Enabled: true + +Lint/NextWithoutAccumulator: + Description: Do not omit the accumulator when calling `next` in a `reduce`/`inject` + block. + +Lint/NonLocalExitFromIterator: + Enabled: true + +Lint/ParenthesesAsGroupedExpression: + Enabled: true + +Lint/PercentStringArray: + Enabled: true + +Lint/PercentSymbolArray: + Enabled: true + +Lint/RandOne: + Description: Checks for `rand(1)` calls. Such calls always return `0` and most + likely a mistake. + +Lint/RequireParentheses: + Enabled: true + +Lint/RescueException: + Enabled: true + +Lint/ShadowedException: + Enabled: true + +Lint/ShadowingOuterLocalVariable: + Enabled: true + +Lint/StringConversionInInterpolation: + Enabled: true + +Lint/UnderscorePrefixedVariableName: + Enabled: true + +Lint/UnifiedInteger: + Enabled: true + +Lint/UnneededCopDisableDirective: + Enabled: true + +Lint/UnneededCopEnableDirective: + Enabled: true + +Lint/UnneededSplatExpansion: + Enabled: true + +Lint/UnreachableCode: + Enabled: true + +Lint/UselessAccessModifier: + ContextCreatingMethods: [] + +Lint/UselessAssignment: + Enabled: true + +Lint/UselessComparison: + Enabled: true + +Lint/UselessElseWithoutRescue: + Enabled: true + +Lint/UselessSetterCall: + Enabled: true + +Lint/Void: + Enabled: true + +Performance/CaseWhenSplat: + Enabled: true + +Performance/Count: + SafeMode: true + +Performance/Detect: + SafeMode: true + +Performance/DoubleStartEndWith: + Enabled: true + +Performance/EndWith: + Enabled: true + +Performance/FixedSize: + Enabled: true + +Performance/FlatMap: + EnabledForFlattenWithoutParams: false + +Performance/LstripRstrip: + Enabled: true + +Performance/RangeInclude: + Enabled: true + +Performance/RedundantBlockCall: + Enabled: true + +Performance/RedundantMatch: + Enabled: true + +Performance/RedundantSortBy: + Enabled: true + +Performance/ReverseEach: + Enabled: true + +Performance/Sample: + Enabled: true + +Performance/Size: + Enabled: true + +Performance/CompareWithBlock: + Enabled: true + +Performance/StartWith: + Enabled: true + +Performance/StringReplacement: + Enabled: true + +Rails/DelegateAllowBlank: + Enabled: true + +Rails/HttpPositionalArguments: + Include: + - spec/**/* + - test/**/* + +Rails/OutputSafety: + Enabled: true + +Rails/PluralizationGrammar: + Enabled: true + +Security/Eval: + Enabled: true + +Security/JSONLoad: + Enabled: true + +Security/Open: + Enabled: true + +Lint/BigDecimalNew: + Enabled: true + +Style/TrailingBodyOnClass: + Enabled: true + +Style/TrailingBodyOnModule: + Enabled: true + +Style/TrailingCommaInArrayLiteral: + EnforcedStyleForMultiline: comma + Enabled: true + +Style/TrailingCommaInHashLiteral: + EnforcedStyleForMultiline: comma + Enabled: true + +Layout/SpaceInsideReferenceBrackets: + EnforcedStyle: no_space + EnforcedStyleForEmptyBrackets: no_space + Enabled: true + +Style/ModuleFunction: + EnforcedStyle: extend_self + +Lint/OrderedMagicComments: + Enabled: true diff --git a/Gemfile b/Gemfile index 8d98a1a6..97df7455 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source 'https://rubygems.org' git_source(:github) do |repo_name| @@ -67,12 +69,16 @@ group :development, :test do # Environment configuration. gem 'dotenv-rails' + + # Ruby linting. + gem 'rubocop' end group :test do # Include Rspec and other testing utilities. gem 'rspec-rails', '~> 3.7' gem 'action-cable-testing' + gem 'rails-controller-testing' gem 'shoulda-matchers', '~> 3.1' gem 'faker' gem "factory_bot_rails" diff --git a/Gemfile.lock b/Gemfile.lock index 0477756c..fe663602 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -41,6 +41,7 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) arel (7.1.4) + ast (2.4.0) autoprefixer-rails (8.6.2) execjs bcrypt (3.1.12) @@ -84,6 +85,7 @@ GEM hashie (3.5.7) i18n (1.0.1) concurrent-ruby (~> 1.0) + jaro_winkler (1.5.1) jbuilder (2.7.0) activesupport (>= 4.2.0) multi_json (>= 1.2) @@ -133,8 +135,12 @@ GEM omniauth-twitter (1.4.0) omniauth-oauth (~> 1.1) rack + parallel (1.12.1) + parser (2.5.1.0) + ast (~> 2.4.0) pg (0.21.0) popper_js (1.12.9) + powerpack (0.1.2) puma (3.11.4) rack (2.0.5) rack-test (0.6.3) @@ -151,6 +157,10 @@ GEM bundler (>= 1.3.0) railties (= 5.0.7) sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.2) + actionpack (~> 5.x, >= 5.0.1) + actionview (~> 5.x, >= 5.0.1) + activesupport (~> 5.x) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) @@ -162,6 +172,7 @@ GEM method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) + rainbow (3.0.0) rake (12.3.1) rb-fsevent (0.10.3) rb-inotify (0.9.10) @@ -184,6 +195,15 @@ GEM rspec-mocks (~> 3.7.0) rspec-support (~> 3.7.0) rspec-support (3.7.1) + rubocop (0.57.2) + jaro_winkler (~> 1.5.1) + parallel (~> 1.10) + parser (>= 2.5) + powerpack (~> 0.1) + rainbow (>= 2.2.2, < 4.0) + ruby-progressbar (~> 1.7) + unicode-display_width (~> 1.0, >= 1.0.1) + ruby-progressbar (1.9.0) sass (3.5.6) sass-listen (~> 4.0.0) sass-listen (4.0.0) @@ -222,6 +242,7 @@ GEM thread_safe (~> 0.1) uglifier (4.1.11) execjs (>= 0.3.0, < 3) + unicode-display_width (1.4.0) web-console (3.6.2) actionview (>= 5.0) activemodel (>= 5.0) @@ -254,8 +275,10 @@ DEPENDENCIES pg (~> 0.18) puma (~> 3.0) rails (~> 5.0.7) + rails-controller-testing redis (~> 3.0) rspec-rails (~> 3.7) + rubocop sass-rails (~> 5.0) shoulda-matchers (~> 3.1) spring diff --git a/Rakefile b/Rakefile index e85f9139..488c551f 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb index d6726972..9aec2305 100644 --- a/app/channels/application_cable/channel.rb +++ b/app/channels/application_cable/channel.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ApplicationCable class Channel < ActionCable::Channel::Base end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index 0ff5442f..8d6c2a1b 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ApplicationCable class Connection < ActionCable::Connection::Base end diff --git a/app/channels/waiting_channel.rb b/app/channels/waiting_channel.rb index 8c28e236..318872e8 100644 --- a/app/channels/waiting_channel.rb +++ b/app/channels/waiting_channel.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class WaitingChannel < ApplicationCable::Channel def subscribed stream_from "#{params[:uid]}_waiting_channel" diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 91673a70..0f07f83b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'bigbluebutton_api' class ApplicationController < ActionController::Base @@ -43,18 +45,18 @@ class ApplicationController < ActionController::Base # Determines if a form field needs the is-invalid class. def form_is_invalid?(obj, key) - 'is-invalid' if !obj.errors.messages[key].empty? + 'is-invalid' unless obj.errors.messages[key].empty? end helper_method :form_is_invalid? - + # Default, unconfigured meeting options. def default_meeting_options + invite_msg = "To invite someone to the meeting, send them this link:" { user_is_moderator: false, meeting_logout_url: request.base_url + logout_room_path(@room), meeting_recorded: true, - moderator_message: "To invite someone to the meeting, send them this link:\n\n - #{request.base_url + relative_root + room_path(@room)}" + moderator_message: "#{invite_msg}\n\n #{request.base_url + relative_root + room_path(@room)}", } end end diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index fd44434d..73c623f0 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -1,9 +1,10 @@ +# frozen_string_literal: true + class ErrorsController < ApplicationController - def not_found render status: 404 end - + def unprocessable render status: 422 end diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 41632536..b7f7ff97 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -1,6 +1,7 @@ -class MainController < ApplicationController +# frozen_string_literal: true - #before_action :redirect_to_room +class MainController < ApplicationController + # before_action :redirect_to_room # GET / def index diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 8180bb36..e8da0d64 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -1,5 +1,6 @@ -class RoomsController < ApplicationController +# frozen_string_literal: true +class RoomsController < ApplicationController before_action :validate_accepted_terms, unless: -> { !Rails.configuration.terms } before_action :find_room, except: :create before_action :verify_room_ownership, except: [:create, :show, :join, :logout] @@ -9,7 +10,7 @@ class RoomsController < ApplicationController # POST / def create redirect_to root_path unless current_user - + @room = Room.new(name: room_params[:name]) @room.owner = current_user @@ -19,9 +20,6 @@ class RoomsController < ApplicationController else redirect_to @room end - else - # Handle room didn't save. - end end @@ -29,7 +27,7 @@ class RoomsController < ApplicationController def show if current_user && @room.owned_by?(current_user) @recordings = @room.recordings - @is_running = @room.is_running? + @is_running = @room.running? else render :join end @@ -47,7 +45,7 @@ class RoomsController < ApplicationController return end - if @room.is_running? + if @room.running? if current_user redirect_to @room.join_path(current_user.name, opts, current_user.uid) else @@ -92,13 +90,13 @@ class RoomsController < ApplicationController current_user.main_room = @room current_user.save - redirect_to @room + redirect_to @room end # POST /:room_uid/:record_id def update_recording meta = { - "meta_#{META_LISTED}" => (params[:state] == "public") + "meta_#{META_LISTED}" => (params[:state] == "public"), } res = @room.update_recording(params[:record_id], meta) @@ -124,12 +122,10 @@ class RoomsController < ApplicationController if len > 60 "#{len / 60} hrs" + elsif len == 0 + "< 1 min" else - if len == 0 - "< 1 min" - else - "#{len} min" - end + "#{len} min" end end helper_method :recording_length @@ -147,7 +143,7 @@ class RoomsController < ApplicationController # Ensure the user is logged into the room they are accessing. def verify_room_ownership - bring_to_room if !@room.owned_by?(current_user) + bring_to_room unless @room.owned_by?(current_user) end # Redirects a user to their room. diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index deee494e..8f9b0028 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,5 +1,6 @@ -class SessionsController < ApplicationController +# frozen_string_literal: true +class SessionsController < ApplicationController # GET /users/login def new end @@ -13,11 +14,8 @@ class SessionsController < ApplicationController # POST /users/login def create user = User.find_by(email: session_params[:email]) - if user && user.authenticate(session_params[:password]) + if user.&authenticate(session_params[:password]) login(user) - else - # Login unsuccessful, display error message. - end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index f7af4543..d231c994 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,6 @@ -class UsersController < ApplicationController +# frozen_string_literal: true +class UsersController < ApplicationController before_action :find_user, only: [:edit, :update] before_action :ensure_unauthenticated, only: [:new, :create] @@ -12,7 +13,7 @@ class UsersController < ApplicationController @user.provider = "greenlight" if @user.save - login(@user) + login(@user) else # Handle error on user creation. render :new @@ -61,16 +62,13 @@ class UsersController < ApplicationController redirect_to edit_user_path(@user), notice: "Information successfully updated." else # Append custom errors. - errors.each do |k, v| @user.errors.add(k, v) end + errors.each { |k, v| @user.errors.add(k, v) } render :edit end + elsif @user.update_attributes(user_params) + redirect_to edit_user_path(@user), notice: "Information successfully updated." else - # Update the core user attributes. - if @user.update_attributes(user_params) - redirect_to edit_user_path(@user), notice: "Information successfully updated." - else - render :edit - end + render :edit end end @@ -83,7 +81,7 @@ class UsersController < ApplicationController redirect_to current_user.main_room end end - + private def find_user diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 039b657b..4795f423 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ApplicationHelper include MeetingsHelper @@ -12,7 +14,7 @@ module ApplicationHelper def omniauth_login_url(provider) "#{Rails.configuration.relative_url_root}/auth/#{provider}" end - + # Determine if Greenlight is configured to allow user signups. def allow_user_signup? Rails.configuration.allow_user_signup diff --git a/app/helpers/errors_helper.rb b/app/helpers/errors_helper.rb index 8e3b415c..4e0bcb87 100644 --- a/app/helpers/errors_helper.rb +++ b/app/helpers/errors_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module ErrorsHelper end diff --git a/app/helpers/main_helper.rb b/app/helpers/main_helper.rb index 826effed..b95f19dc 100644 --- a/app/helpers/main_helper.rb +++ b/app/helpers/main_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module MainHelper end diff --git a/app/helpers/meetings_helper.rb b/app/helpers/meetings_helper.rb index bdf52802..381b3326 100644 --- a/app/helpers/meetings_helper.rb +++ b/app/helpers/meetings_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module MeetingsHelper end diff --git a/app/helpers/rooms_helper.rb b/app/helpers/rooms_helper.rb index 1d0f4c73..60bf7cc6 100644 --- a/app/helpers/rooms_helper.rb +++ b/app/helpers/rooms_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module RoomsHelper end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index 8b45de68..d5f11bdb 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + module SessionsHelper - # Logs a user into GreenLight. def login(user) session[:user_id] = user.id # If there are not terms, or the user has accepted them, go to their room. - if !Rails.configuration.terms || user.accepted_terms then + if !Rails.configuration.terms || user.accepted_terms redirect_to user.main_room else redirect_to terms_path diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 2310a240..4dc909ed 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module UsersHelper end diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb index a009ace5..d92ffddc 100644 --- a/app/jobs/application_job.rb +++ b/app/jobs/application_job.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + class ApplicationJob < ActiveJob::Base end diff --git a/app/jobs/notify_user_waiting_job.rb b/app/jobs/notify_user_waiting_job.rb index 3c399c5a..e3da86e7 100644 --- a/app/jobs/notify_user_waiting_job.rb +++ b/app/jobs/notify_user_waiting_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class NotifyUserWaitingJob < ApplicationJob queue_as :default diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 286b2239..d84cb6e7 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ApplicationMailer < ActionMailer::Base default from: 'from@example.com' layout 'mailer' diff --git a/app/models/application_record.rb b/app/models/application_record.rb index e0f5f7bb..7c4440de 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + class ApplicationRecord < ActiveRecord::Base self.abstract_class = true - + def to_param - uid + uid end end diff --git a/app/models/room.rb b/app/models/room.rb index 65d5bb5d..52bf5262 100644 --- a/app/models/room.rb +++ b/app/models/room.rb @@ -1,5 +1,6 @@ -class Room < ApplicationRecord +# frozen_string_literal: true +class Room < ApplicationRecord before_create :setup validates :name, presence: true @@ -8,7 +9,6 @@ class Room < ApplicationRecord RETURNCODE_SUCCESS = "SUCCESS" META_LISTED = "gl-listed" - UID_LENGTH = 6 # Determines if a user owns a room. def owned_by?(user) @@ -17,7 +17,7 @@ class Room < ApplicationRecord end # Checks if a room is running on the BigBlueButton server. - def is_running? + def running? bbb.is_meeting_running?(bbb_id) end @@ -34,16 +34,11 @@ class Room < ApplicationRecord moderatorPW: random_password(12), attendeePW: random_password(12), moderatorOnlyMessage: options[:moderator_message], - "meta_#{META_LISTED}": false + "meta_#{META_LISTED}": false, } # Update session info. - self.update_attributes(sessions: sessions + 1, last_session: DateTime.now) - - #meeting_options.merge!( - #{ "meta_room-id": options[:room_owner], - # "meta_meeting-name": options[:meeting_name]} - #) if options[:room_owner] + update_attributes(sessions: sessions + 1, last_session: DateTime.now) # Send the create request. begin @@ -56,7 +51,7 @@ class Room < ApplicationRecord # Returns a URL to join a user into a meeting. def join_path(name, options = {}, uid = nil) # Create the meeting if it isn't running. - start_session(options) unless is_running? + start_session(options) unless running? # Set meeting options. options[:meeting_logout_url] ||= nil @@ -64,7 +59,7 @@ class Room < ApplicationRecord options[:user_is_moderator] ||= false options[:meeting_recorded] ||= false - return call_invalid_res if !bbb + return call_invalid_res unless bbb # Get the meeting info. meeting_info = bbb.get_meeting_info(bbb_id, nil) @@ -78,30 +73,26 @@ class Room < ApplicationRecord # Generate the join URL. join_opts = {} - join_opts.merge!({userID: uid}) if uid - join_opts.merge!({joinViaHtml5: true}) if Rails.configuration.html5_enabled - + join_opts[:userID] = uid if uid + join_opts[:joinViaHtml5] = true if Rails.configuration.html5_enabled + bbb.join_meeting_url(bbb_id, name, password, join_opts) end # Notify waiting users that a meeting has started. def notify_waiting - ActionCable.server.broadcast("#{uid}_waiting_channel", { - action: "started" - }) + ActionCable.server.broadcast("#{uid}_waiting_channel", action: "started") end # Retrieves all the users in a room. def participants - begin - res = bbb.get_meeting_info(bbb_id, nil) - res[:attendees].map do |att| - User.find_by(uid: att[:userID], name: att[:fullName]) - end - rescue BigBlueButton::BigBlueButtonException => exc - # The meeting is most likely not running. - [] + res = bbb.get_meeting_info(bbb_id, nil) + res[:attendees].map do |att| + User.find_by(uid: att[:userID], name: att[:fullName]) end + rescue BigBlueButton::BigBlueButtonException + # The meeting is most likely not running. + [] end # Fetches all recordings for a room. @@ -120,18 +111,18 @@ class Room < ApplicationRecord end r.delete(:playback) - end + end res[:recordings] end # Fetches a rooms public recordings. def public_recordings - recordings.select do |r| r[:metadata][:"gl-listed"] == "true" end + recordings.select { |r| r[:metadata][:"gl-listed"] == "true" } end def update_recording(record_id, meta) - meta.merge!({recordID: record_id}) + meta[:recordID] = record_id bbb.send_api_request("updateRecordings", meta) end @@ -153,12 +144,12 @@ class Room < ApplicationRecord # Sets a BigBlueButtonApi object for interacting with the API. def bbb @bbb ||= BigBlueButton::BigBlueButtonApi.new(remove_slash(bbb_endpoint), bbb_secret, "0.8") - #@bbb ||= if Rails.configuration.loadbalanced_configuration - # lb_user = retrieve_loadbalanced_credentials(self.room.owner.provider) - # BigBlueButton::BigBlueButtonApi.new(remove_slash(lb_user["apiURL"]), lb_user["secret"], "0.8") - #else - # BigBlueButton::BigBlueButtonApi.new(remove_slash(bbb_endpoint), bbb_secret, "0.8") - #end + # @bbb ||= if Rails.configuration.loadbalanced_configuration + # lb_user = retrieve_loadbalanced_credentials(self.room.owner.provider) + # BigBlueButton::BigBlueButtonApi.new(remove_slash(lb_user["apiURL"]), lb_user["secret"], "0.8") + # else + # BigBlueButton::BigBlueButtonApi.new(remove_slash(bbb_endpoint), bbb_secret, "0.8") + # end end # Generates a uid for the room and BigBlueButton. @@ -167,10 +158,15 @@ class Room < ApplicationRecord self.bbb_id = Digest::SHA1.hexdigest(Rails.application.secrets[:secret_key_base] + Time.now.to_i.to_s).to_s end + # Generates a three character uid chunk. + def uid_chunk + charset = ("a".."z").to_a - %w(b i l o s) + ("2".."9").to_a - %w(5 8) + (0...3).map { charset.to_a[rand(charset.size)] }.join + end + # Generates a random room uid that uses the users name. def random_room_uid - charset = %w{ 2 3 4 6 7 9 a c d e f g h j k m n p q r t v w x y z} - owner.firstname.downcase + "-" + (0...UID_LENGTH).map{ charset.to_a[rand(charset.size)] }.join.insert(UID_LENGTH / 2, "-") + [owner.firstname, uid_chunk, uid_chunk].join('-').downcase end # Rereives the loadbalanced BigBlueButton credentials for a user. @@ -182,7 +178,7 @@ class Room < ApplicationRecord uri = encode_bbb_url( Rails.configuration.loadbalancer_endpoint, Rails.configuration.loadbalancer_secret, - {name: provider} + name: provider ) # Make the request. @@ -190,7 +186,7 @@ class Room < ApplicationRecord http.use_ssl = (uri.scheme == 'https') response = http.get(uri.request_uri) - unless response.kind_of?(Net::HTTPSuccess) + unless response.is_a?(Net::HTTPSuccess) raise "Error retrieving provider credentials: #{response.code} #{response.message}" end @@ -209,7 +205,7 @@ class Room < ApplicationRecord encoded_params = OAuth::Helper.normalize(params) string = "getUser" + encoded_params + secret checksum = OpenSSL::Digest.digest('sha1', string).unpack("H*").first - + URI.parse("#{base_url}?#{encoded_params}&checksum=#{checksum}") end @@ -220,7 +216,7 @@ class Room < ApplicationRecord # Generates a random password for a meeting. def random_password(length) - o = ([('a'..'z'), ('A'..'Z')].map do |i| i.to_a end).flatten - ((0...length).map do o[rand(o.length)] end).join + charset = ("a".."z").to_a + ("A".."Z").to_a + ((0...length).map { charset[rand(charset.length)] }).join end end diff --git a/app/models/user.rb b/app/models/user.rb index 2c63c7b3..a89becb2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,17 +1,18 @@ -class User < ApplicationRecord +# frozen_string_literal: true +class User < ApplicationRecord after_create :initialize_main_room - before_save { email.downcase! unless email.nil? } + before_save { email.try(:downcase!) } has_many :rooms belongs_to :main_room, class_name: 'Room', foreign_key: :room_id, required: false validates :name, length: { maximum: 24 }, presence: true validates :provider, presence: true - validates :image, format: {with: /\.(png|jpg)\Z/i}, allow_blank: true + validates :image, format: { with: /\.(png|jpg)\Z/i }, allow_blank: true validates :email, length: { maximum: 60 }, allow_blank: true, uniqueness: { case_sensitive: false }, - format: {with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i } + format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i } validates :password, length: { minimum: 6 }, confirmation: true, if: :greenlight_account? @@ -19,26 +20,15 @@ class User < ApplicationRecord has_secure_password(validations: false) class << self - # Generates a user from omniauth. def from_omniauth(auth) - user = find_or_initialize_by( - social_uid: auth['uid'], - provider: auth['provider'] - ) - - user.name = send("#{auth['provider']}_name", auth) - user.username = send("#{auth['provider']}_username", auth) - user.email = send("#{auth['provider']}_email", auth) - user.image = send("#{auth['provider']}_image", auth) - - user.save! - user - end - - # Generates a user from a trusted launcher. - def from_launch(auth) - + find_or_initialize_by(social_uid: auth['uid'], provider: auth['provider']).tap do |u| + u.name = send("#{auth['provider']}_name", auth) + u.username = send("#{auth['provider']}_username", auth) + u.email = send("#{auth['provider']}_email", auth) + u.image = send("#{auth['provider']}_image", auth) + u.save! + end end private @@ -80,9 +70,9 @@ class User < ApplicationRecord # Retrives a list of all a users rooms that are not the main room, sorted by last session date. def secondary_rooms secondary = (rooms - [main_room]) - no_session, session = secondary.partition do |r| r.last_session.nil? end - sorted = session.sort_by do |r| r.last_session end - session + no_session + no_session, session = secondary.partition { |r| r.last_session.nil? } + sorted = session.sort_by(&:last_session) + sorted + no_session end def firstname @@ -99,6 +89,6 @@ class User < ApplicationRecord def initialize_main_room self.uid = "gl-#{(0...12).map { (65 + rand(26)).chr }.join.downcase}" self.main_room = Room.create!(owner: self, name: firstname + "'s Room") - self.save + save end end diff --git a/bin/bundle b/bin/bundle index 66e9889e..58115ecf 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,3 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails index 5badb2fd..a3655392 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + begin load File.expand_path('../spring', __FILE__) rescue LoadError => e diff --git a/bin/rake b/bin/rake index d87d5f57..169c9396 100755 --- a/bin/rake +++ b/bin/rake @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + begin load File.expand_path('../spring', __FILE__) rescue LoadError => e diff --git a/bin/setup b/bin/setup index e620b4da..629e3584 100755 --- a/bin/setup +++ b/bin/setup @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require 'pathname' require 'fileutils' include FileUtils diff --git a/bin/spring b/bin/spring index fb2ec2eb..df22d97b 100755 --- a/bin/spring +++ b/bin/spring @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true # This file loads spring without using Bundler, in order to be fast. # It gets overwritten when you run the `spring binstub` command. diff --git a/bin/update b/bin/update index a8e4462f..fdac831b 100755 --- a/bin/update +++ b/bin/update @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require 'pathname' require 'fileutils' include FileUtils diff --git a/config.ru b/config.ru index 66285118..d5199a18 100644 --- a/config.ru +++ b/config.ru @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file is used by Rack-based servers to start the application. require_relative 'config/environment' diff --git a/config/application.rb b/config/application.rb index a65ba8f8..ae323d4d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative 'boot' require 'rails/all' @@ -13,12 +15,16 @@ module Greenlight # -- all .rb files in that directory are automatically loaded. # Use custom error routes. - config.exceptions_app = self.routes + config.exceptions_app = routes config.loadbalanced_configuration = (ENV["USE_LOADBALANCED_CONFIGURATION"] == "true") # Setup BigBlueButton configuration. - unless config.loadbalanced_configuration + if config.loadbalanced_configuration + # Fetch credentials from a loadbalancer based on provider. + config.loadbalancer_endpoint = ENV["LOADBALANCER_ENDPOINT"] + config.loadbalancer_secret = ENV["LOADBALANCER_SECRET"] + else # Default credentials (test-install.blindsidenetworks.com/bigbluebutton). config.bigbluebutton_endpoint_default = "http://test-install.blindsidenetworks.com/bigbluebutton/api/" config.bigbluebutton_secret_default = "8cd8ef52e8e101574e400365b55e11a6" @@ -35,10 +41,6 @@ module Greenlight # Fix endpoint format if required. config.bigbluebutton_endpoint += "api/" unless config.bigbluebutton_endpoint.ends_with?('api/') - else - # Fetch credentials from a loadbalancer based on provider. - config.loadbalancer_endpoint = ENV["LOADBALANCER_ENDPOINT"] - config.loadbalancer_secret = ENV["LOADBALANCER_SECRET"] end # Determine if GreenLight should allow non-omniauth signup/login. diff --git a/config/boot.rb b/config/boot.rb index 30f5120d..30e594e2 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/environment.rb b/config/environment.rb index 426333bb..d5abe558 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Load the Rails application. require_relative 'application' diff --git a/config/environments/development.rb b/config/environments/development.rb index 4b601329..3027e432 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -18,7 +20,7 @@ Rails.application.configure do config.cache_store = :memory_store config.public_file_server.headers = { - 'Cache-Control' => 'public, max-age=172800' + 'Cache-Control' => 'public, max-age=172800', } else config.action_controller.perform_caching = false diff --git a/config/environments/production.rb b/config/environments/production.rb index 1e6aa690..42d2e076 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -47,7 +49,7 @@ Rails.application.configure do config.log_level = :debug # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Use a different cache store in production. # config.cache_store = :mem_cache_store @@ -85,9 +87,6 @@ Rails.application.configure do config.active_record.dump_schema_after_migration = false # Set the relative url root for deployment to a subdirectory. - if ENV['RELATIVE_URL_ROOT'].present? - config.relative_url_root = ENV['RELATIVE_URL_ROOT'] - else - config.relative_url_root = "/" - end + config.relative_url_root = "/" + config.relative_url_root = ENV['RELATIVE_URL_ROOT'] if ENV['RELATIVE_URL_ROOT'].present? end diff --git a/config/environments/test.rb b/config/environments/test.rb index 30587ef6..0c28efe9 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -15,7 +17,7 @@ Rails.application.configure do # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { - 'Cache-Control' => 'public, max-age=3600' + 'Cache-Control' => 'public, max-age=3600', } # Show full error reports and disable caching. diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb index 89d2efab..6d56e439 100644 --- a/config/initializers/application_controller_renderer.rb +++ b/config/initializers/application_controller_renderer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # ActiveSupport::Reloader.to_prepare do diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 54a967b3..3d3fd61d 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index 59385cdf..4b63f289 100644 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 5a6a32d3..ee8dff9c 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 4a994e1e..7a4f47b4 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. diff --git a/config/initializers/html5.rb b/config/initializers/html5.rb index b5994f85..635767a5 100644 --- a/config/initializers/html5.rb +++ b/config/initializers/html5.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Send a request to check if the HTML5 client is enabled on the BigBlueButton server. uri = URI.parse(Rails.configuration.bigbluebutton_endpoint.gsub('bigbluebutton/api', 'html5client/check')) res = Net::HTTP.get_response(uri) diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index ac033bf9..dc847422 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index dc189968..be6fedc5 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb index dd236b5f..377b6532 100644 --- a/config/initializers/new_framework_defaults.rb +++ b/config/initializers/new_framework_defaults.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # # This file contains migration options to ease your Rails 5.0 upgrade. diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb index cb6a02ca..16f154ad 100644 --- a/config/initializers/omniauth.rb +++ b/config/initializers/omniauth.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # List of supported Omniauth providers. Rails.application.config.providers = [:google, :twitter] @@ -10,8 +12,8 @@ Rails.application.config.middleware.use OmniAuth::Builder do provider :twitter, ENV['TWITTER_ID'], ENV['TWITTER_SECRET'] provider :google_oauth2, ENV['GOOGLE_OAUTH2_ID'], ENV['GOOGLE_OAUTH2_SECRET'], - scope: ['profile', 'email'], + scope: %w(profile email), access_type: 'online', name: 'google', hd: ENV['GOOGLE_OAUTH2_HD'].blank? ? nil : ENV['GOOGLE_OAUTH2_HD'] -end \ No newline at end of file +end diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index a65e450f..f8324089 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. Rails.application.config.session_store :cookie_store, key: '_greenlight-2_0_session' diff --git a/config/initializers/terms.rb b/config/initializers/terms.rb index ebfdb57d..26e5da70 100644 --- a/config/initializers/terms.rb +++ b/config/initializers/terms.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Load terms and conditions. terms = "#{Rails.root}/config/terms.txt" diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index bbfc3961..2f3c0db4 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/config/puma.rb b/config/puma.rb index c7f311f8..991c3a6f 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Puma can serve each request in a thread from an internal thread pool. # The `threads` method setting takes two numbers a minimum and maximum. # Any libraries that use thread pools should be configured to match diff --git a/config/routes.rb b/config/routes.rb index 047f1d46..924b1191 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,6 @@ -Rails.application.routes.draw do +# frozen_string_literal: true +Rails.application.routes.draw do # Error routes. match '/404', to: 'errors#not_found', via: :all match '/422', to: 'errors#unprocessable', via: :all @@ -15,7 +16,7 @@ Rails.application.routes.draw do # Handles login of greenlight provider accounts. post '/login', to: 'sessions#create', as: :create_session - + # Log the user out of the session. get '/logout', to: 'sessions#destroy' @@ -39,7 +40,7 @@ Rails.application.routes.draw do post '/start', to: 'rooms#start', as: :start_room get '/logout', to: 'rooms#logout', as: :logout_room post '/home', to: 'rooms#home', as: :make_home - + # Mange recordings. scope '/:record_id' do post '/', to: 'rooms#update_recording', as: :update_recording diff --git a/config/spring.rb b/config/spring.rb index c9119b40..ff5ba06b 100644 --- a/config/spring.rb +++ b/config/spring.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + %w( .ruby-version .rbenv-vars diff --git a/db/migrate/20180504131648_create_users.rb b/db/migrate/20180504131648_create_users.rb index f919e286..74dd9bf3 100644 --- a/db/migrate/20180504131648_create_users.rb +++ b/db/migrate/20180504131648_create_users.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateUsers < ActiveRecord::Migration[5.0] def change create_table :users do |t| diff --git a/db/migrate/20180504131705_create_rooms.rb b/db/migrate/20180504131705_create_rooms.rb index 995d108e..5d946354 100644 --- a/db/migrate/20180504131705_create_rooms.rb +++ b/db/migrate/20180504131705_create_rooms.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateRooms < ActiveRecord::Migration[5.0] def change create_table :rooms do |t| diff --git a/db/seeds.rb b/db/seeds.rb index 1beea2ac..ebd18895 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). # diff --git a/lib/tasks/configuration.rake b/lib/tasks/configuration.rake index 4beb92ec..bb15c066 100644 --- a/lib/tasks/configuration.rake +++ b/lib/tasks/configuration.rake @@ -1,11 +1,13 @@ +# frozen_string_literal: true + require 'net/http' require 'nokogiri' require 'digest/sha1' -namespace :conf do +namespace :conf do desc "Check Configuration" - task :check => :environment do - ENV_VARIABLES = ['SECRET_KEY_BASE', 'BIGBLUEBUTTON_ENDPOINT', 'BIGBLUEBUTTON_SECRET'] + task check: :environment do + ENV_VARIABLES = %w(SECRET_KEY_BASE BIGBLUEBUTTON_ENDPOINT BIGBLUEBUTTON_SECRET) # Initial check that variables are set print "\nChecking environment" @@ -31,17 +33,15 @@ end # takes the full URL including the protocol def test_request(url) - begin - uri = URI(url) - res = Net::HTTP.get(uri) + uri = URI(url) + res = Net::HTTP.get(uri) - doc = Nokogiri::XML(res) - if doc.css("returncode").text != "SUCCESS" - failed("Could not get a valid response from BigBlueButton server - #{res}") - end - rescue => exc - failed("Error connecting to BigBlueButton server - #{exc}") + doc = Nokogiri::XML(res) + if doc.css("returncode").text != "SUCCESS" + failed("Could not get a valid response from BigBlueButton server - #{res}") end +rescue => exc + failed("Error connecting to BigBlueButton server - #{exc}") end def failed(msg) @@ -49,6 +49,6 @@ def failed(msg) exit end -def passed() +def passed print(": Passed\n") end diff --git a/spec/factories.rb b/spec/factories.rb index 6cf52189..d99ff9d0 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true + FactoryBot.define do - factory :user do password = Faker::Internet.password(8) provider { %w(greenlight google twitter).sample } - uid { rand(10 ** 8) } + uid { rand(10**8) } name { Faker::Name.first_name } username { Faker::Internet.user_name } email { Faker::Internet.email } diff --git a/spec/models/room_spec.rb b/spec/models/room_spec.rb index 7e9361a0..12f0df90 100644 --- a/spec/models/room_spec.rb +++ b/spec/models/room_spec.rb @@ -1,12 +1,13 @@ +# frozen_string_literal: true + require "rails_helper" require 'bigbluebutton_api' describe Room, type: :model do - - before { + before do @user = create(:user) @room = @user.main_room - } + end context 'validations' do it { should validate_presence_of(:name) } @@ -45,14 +46,14 @@ describe Room, type: :model do end end - context "#is_running?" do + context "#running?" do it "should return false when not running" do - expect(@room.is_running?).to be false + expect(@room.running?).to be false end it "should return true when running" do allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:is_meeting_running?).and_return(true) - expect(@room.is_running?).to be true + expect(@room.running?).to be true end end @@ -60,11 +61,9 @@ describe Room, type: :model do it "should update latest session info" do allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:create_meeting).and_return(true) - expect{ + expect do @room.start_session - }.to change { - @room.sessions - }.by(1) + end.to change { @room.sessions }.by(1) expect(@room.last_session.utc.to_i).to eq(Time.now.to_i) end @@ -72,33 +71,31 @@ describe Room, type: :model do context "#join_path" do it "should return correct join URL for user" do - allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_meeting_info).and_return({ + allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_meeting_info).and_return( attendeePW: "testpass" - }) + ) endpoint = Rails.configuration.bigbluebutton_endpoint secret = Rails.configuration.bigbluebutton_secret fullname = "fullName=Example" - html = if Rails.configuration.html5_enabled then "&joinViaHtml5=true" else "" end - meetingID = "&meetingID=#{@room.bbb_id}" + html = Rails.configuration.html5_enabled ? "&joinViaHtml5=true" : "" + meeting_id = "&meetingID=#{@room.bbb_id}" password = "&password=testpass" - query = fullname + html + meetingID + password + query = fullname + html + meeting_id + password checksum_string = "join#{query + secret}" checksum = OpenSSL::Digest.digest('sha1', checksum_string).unpack("H*").first - expect(@room.join_path("Example")).to eql( - "#{endpoint}join?#{query}&checksum=#{checksum}" - ) + expect(@room.join_path("Example")).to eql("#{endpoint}join?#{query}&checksum=#{checksum}") end end context "#notify_waiting" do it "should broadcast to waiting channel with started action" do - expect{ + expect do @room.notify_waiting - }.to have_broadcasted_to("#{@room.uid}_waiting_channel").with(a_hash_including(action: "started")) + end.to have_broadcasted_to("#{@room.uid}_waiting_channel").with(a_hash_including(action: "started")) end end @@ -107,13 +104,13 @@ describe Room, type: :model do user1 = create(:user) user2 = create(:user) - allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_meeting_info).and_return({ + allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_meeting_info).and_return( attendees: [ - {userID: user1.uid, fullName: user1.name}, - {userID: "non-matching-uid", fullName: "Guest User"}, - {userID: user2.uid, fullName: user2.name} - ] - }) + { userID: user1.uid, fullName: user1.name }, + { userID: "non-matching-uid", fullName: "Guest User" }, + { userID: user2.uid, fullName: user2.name }, + ], + ) expect(@room.participants).to contain_exactly(user1, nil, user2) end @@ -121,21 +118,21 @@ describe Room, type: :model do context "#recordings" do it "should properly find meeting recordings" do - allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return({ + allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_recordings).and_return( recordings: [ { name: "Example", playback: { - format: "presentation" - } + format: "presentation", + }, }, - ] - }) + ], + ) - expect(@room.recordings).to contain_exactly({ + expect(@room.recordings).to contain_exactly( name: "Example", - playbacks: ["presentation"] - }) + playbacks: %w(presentation), + ) end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index b5aef16c..cb0b497c 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,7 +1,11 @@ +# frozen_string_literal: true + require "rails_helper" describe User, type: :model do - before { @user = create(:user) } + before do + @user = create(:user) + end context 'validations' do it { should validate_presence_of(:name) } @@ -21,8 +25,8 @@ describe User, type: :model do it { should allow_value("", nil).for(:image) } it "should convert email to downcase on save" do - user = create(:user, email: "EXAMPLE@EXAMPLE.COM") - expect(user.email).to eq("example@example.com") + user = create(:user, email: "DOWNCASE@DOWNCASE.COM") + expect(user.email).to eq("downcase@downcase.com") end context 'is greenlight account' do @@ -63,11 +67,11 @@ describe User, type: :model do "name" => "Test Name", "nickname" => "username", "email" => "test@example.com", - "image" => "example.png" - } + "image" => "example.png", + }, } - - expect { + + expect do user = User.from_omniauth(auth) expect(user.name).to eq("Test Name") @@ -75,9 +79,7 @@ describe User, type: :model do expect(user.image).to eq("example.png") expect(user.provider).to eq("twitter") expect(user.social_uid).to eq("123456789") - }.to change { - User.count - }.by(1) + end.to change { User.count }.by(1) end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 853cb7e1..26bffbde 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file is copied to spec/ when you run 'rails generate rspec:install' require 'spec_helper' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 67faf007..979abe7c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'faker' require 'factory_bot_rails' @@ -50,53 +52,42 @@ RSpec.configure do |config| # Include FactoryGirl. config.include FactoryBot::Syntax::Methods -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # This allows you to limit a spec run to individual examples or groups # you care about by tagging them with `:focus` metadata. When nothing # is tagged with `:focus`, all examples get run. RSpec also provides # aliases for `it`, `describe`, and `context` that include `:focus` # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus + # config.filter_run_when_matching :focus # Allows RSpec to persist some state between runs in order to support # the `--only-failures` and `--next-failure` CLI options. We recommend # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" + # config.example_status_persistence_file_path = "spec/examples.txt" # Limits the available syntax to the non-monkey patched syntax that is # recommended. For more details, see: # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = "doc" - end + # config.disable_monkey_patching! # Print the 10 slowest examples and example groups at the # end of the spec run, to help surface which specs are running # particularly slow. - config.profile_examples = 10 + # config.profile_examples = 10 # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. # --seed 1234 - config.order = :random + # config.order = :random # Seed global randomization in this process using the `--seed` CLI option. # Setting this allows you to use `--seed` to deterministically reproduce # test failures related to randomization by passing the same `--seed` value # as the one that triggered the failure. - Kernel.srand config.seed -=end -end \ No newline at end of file + # Kernel.srand config.seed +end diff --git a/spec/support/shoulda_matchers.rb b/spec/support/shoulda_matchers.rb index e5f3a067..37cafb19 100644 --- a/spec/support/shoulda_matchers.rb +++ b/spec/support/shoulda_matchers.rb @@ -1,9 +1,10 @@ -# Configure Shoulda-Matchers. +# frozen_string_literal: true +# Configure Shoulda-Matchers. Shoulda::Matchers.configure do |config| config.integrate do |with| with.test_framework :rspec - + with.library :rails end end