├── .codeclimate.yml ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── .travis.yml ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── json_api_responders.gemspec ├── lib ├── json_api_responders.rb └── json_api_responders │ ├── config.rb │ ├── errors.rb │ ├── responder.rb │ ├── responder │ ├── actions.rb │ └── sanitizers.rb │ └── version.rb └── spec ├── json_api_responders_spec.rb ├── lib ├── json_api_responders │ ├── config │ │ └── config_spec.rb │ ├── responder │ │ └── actions_spec.rb │ └── responder_spec.rb └── json_api_responders_spec.rb ├── spec_helper.rb └── support └── fake_classes.rb /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | duplication: 4 | enabled: true 5 | config: 6 | languages: 7 | - ruby 8 | - javascript 9 | - python 10 | - php 11 | fixme: 12 | enabled: true 13 | rubocop: 14 | enabled: true 15 | ratings: 16 | paths: 17 | - "**.inc" 18 | - "**.js" 19 | - "**.jsx" 20 | - "**.module" 21 | - "**.php" 22 | - "**.py" 23 | - "**.rb" 24 | exclude_paths: 25 | - spec/ 26 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | test: 11 | name: Ruby ${{ matrix.ruby }} 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | ruby: [2.7, '3.0', 3.1] 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - uses: ruby/setup-ruby@v1 20 | with: 21 | ruby-version: ${{ matrix.ruby }} 22 | bundler-cache: true 23 | - name: Run tests 24 | run: bundle exec rake 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | DisabledByDefault: true 3 | 4 | #################### Lint ################################ 5 | 6 | Lint/AmbiguousOperator: 7 | Description: >- 8 | Checks for ambiguous operators in the first argument of a 9 | method invocation without parentheses. 10 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-as-args' 11 | Enabled: true 12 | 13 | Lint/AmbiguousRegexpLiteral: 14 | Description: >- 15 | Checks for ambiguous regexp literals in the first argument of 16 | a method invocation without parenthesis. 17 | Enabled: true 18 | 19 | Lint/AssignmentInCondition: 20 | Description: "Don't use assignment in conditions." 21 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition' 22 | Enabled: true 23 | 24 | Lint/BlockAlignment: 25 | Description: 'Align block ends correctly.' 26 | Enabled: true 27 | 28 | Lint/CircularArgumentReference: 29 | Description: "Don't refer to the keyword argument in the default value." 30 | Enabled: true 31 | 32 | Lint/ConditionPosition: 33 | Description: >- 34 | Checks for condition placed in a confusing position relative to 35 | the keyword. 36 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#same-line-condition' 37 | Enabled: true 38 | 39 | Lint/Debugger: 40 | Description: 'Check for debugger calls.' 41 | Enabled: true 42 | 43 | Lint/DefEndAlignment: 44 | Description: 'Align ends corresponding to defs correctly.' 45 | Enabled: true 46 | 47 | Lint/DeprecatedClassMethods: 48 | Description: 'Check for deprecated class method calls.' 49 | Enabled: true 50 | 51 | Lint/DuplicateMethods: 52 | Description: 'Check for duplicate methods calls.' 53 | Enabled: true 54 | 55 | Lint/EachWithObjectArgument: 56 | Description: 'Check for immutable argument given to each_with_object.' 57 | Enabled: true 58 | 59 | Lint/ElseLayout: 60 | Description: 'Check for odd code arrangement in an else block.' 61 | Enabled: true 62 | 63 | Lint/EmptyEnsure: 64 | Description: 'Checks for empty ensure block.' 65 | Enabled: true 66 | 67 | Lint/EmptyInterpolation: 68 | Description: 'Checks for empty string interpolation.' 69 | Enabled: true 70 | 71 | Lint/EndAlignment: 72 | Description: 'Align ends correctly.' 73 | Enabled: true 74 | 75 | Lint/EndInMethod: 76 | Description: 'END blocks should not be placed inside method definitions.' 77 | Enabled: true 78 | 79 | Lint/EnsureReturn: 80 | Description: 'Do not use return in an ensure block.' 81 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-return-ensure' 82 | Enabled: true 83 | 84 | Lint/Eval: 85 | Description: 'The use of eval represents a serious security risk.' 86 | Enabled: true 87 | 88 | Lint/FormatParameterMismatch: 89 | Description: 'The number of parameters to format/sprint must match the fields.' 90 | Enabled: true 91 | 92 | Lint/HandleExceptions: 93 | Description: "Don't suppress exception." 94 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions' 95 | Enabled: true 96 | 97 | Lint/InvalidCharacterLiteral: 98 | Description: >- 99 | Checks for invalid character literals with a non-escaped 100 | whitespace character. 101 | Enabled: true 102 | 103 | Lint/LiteralInCondition: 104 | Description: 'Checks of literals used in conditions.' 105 | Enabled: true 106 | 107 | Lint/LiteralInInterpolation: 108 | Description: 'Checks for literals used in interpolation.' 109 | Enabled: true 110 | 111 | Lint/Loop: 112 | Description: >- 113 | Use Kernel#loop with break rather than begin/end/until or 114 | begin/end/while for post-loop tests. 115 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#loop-with-break' 116 | Enabled: true 117 | 118 | Lint/NestedMethodDefinition: 119 | Description: 'Do not use nested method definitions.' 120 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-methods' 121 | Enabled: true 122 | 123 | Lint/NonLocalExitFromIterator: 124 | Description: 'Do not use return in iterator to cause non-local exit.' 125 | Enabled: true 126 | 127 | Lint/ParenthesesAsGroupedExpression: 128 | Description: >- 129 | Checks for method calls with a space before the opening 130 | parenthesis. 131 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces' 132 | Enabled: true 133 | 134 | Lint/RequireParentheses: 135 | Description: >- 136 | Use parentheses in the method call to avoid confusion 137 | about precedence. 138 | Enabled: true 139 | 140 | Lint/RescueException: 141 | Description: 'Avoid rescuing the Exception class.' 142 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues' 143 | Enabled: true 144 | 145 | Lint/ShadowingOuterLocalVariable: 146 | Description: >- 147 | Do not use the same name as outer local variable 148 | for block arguments or block local variables. 149 | Enabled: true 150 | 151 | Lint/StringConversionInInterpolation: 152 | Description: 'Checks for Object#to_s usage in string interpolation.' 153 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-to-s' 154 | Enabled: true 155 | 156 | Lint/UnderscorePrefixedVariableName: 157 | Description: 'Do not use prefix `_` for a variable that is used.' 158 | Enabled: true 159 | 160 | Lint/UnneededDisable: 161 | Description: >- 162 | Checks for rubocop:disable comments that can be removed. 163 | Note: this cop is not disabled when disabling all cops. 164 | It must be explicitly disabled. 165 | Enabled: true 166 | 167 | Lint/UnusedBlockArgument: 168 | Description: 'Checks for unused block arguments.' 169 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars' 170 | Enabled: true 171 | 172 | Lint/UnusedMethodArgument: 173 | Description: 'Checks for unused method arguments.' 174 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars' 175 | Enabled: true 176 | 177 | Lint/UnreachableCode: 178 | Description: 'Unreachable code.' 179 | Enabled: true 180 | 181 | Lint/UselessAccessModifier: 182 | Description: 'Checks for useless access modifiers.' 183 | Enabled: true 184 | 185 | Lint/UselessAssignment: 186 | Description: 'Checks for useless assignment to a local variable.' 187 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars' 188 | Enabled: true 189 | 190 | Lint/UselessComparison: 191 | Description: 'Checks for comparison of something with itself.' 192 | Enabled: true 193 | 194 | Lint/UselessElseWithoutRescue: 195 | Description: 'Checks for useless `else` in `begin..end` without `rescue`.' 196 | Enabled: true 197 | 198 | Lint/UselessSetterCall: 199 | Description: 'Checks for useless setter call to a local variable.' 200 | Enabled: true 201 | 202 | Lint/Void: 203 | Description: 'Possible use of operator/literal/variable in void context.' 204 | Enabled: true 205 | 206 | ###################### Metrics #################################### 207 | 208 | Metrics/AbcSize: 209 | Description: >- 210 | A calculated magnitude based on number of assignments, 211 | branches, and conditions. 212 | Reference: 'http://c2.com/cgi/wiki?AbcMetric' 213 | Enabled: false 214 | Max: 20 215 | 216 | Metrics/BlockNesting: 217 | Description: 'Avoid excessive block nesting' 218 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#three-is-the-number-thou-shalt-count' 219 | Enabled: true 220 | Max: 4 221 | 222 | Metrics/ClassLength: 223 | Description: 'Avoid classes longer than 250 lines of code.' 224 | Enabled: true 225 | Max: 250 226 | 227 | Metrics/CyclomaticComplexity: 228 | Description: >- 229 | A complexity metric that is strongly correlated to the number 230 | of test cases needed to validate a method. 231 | Enabled: true 232 | 233 | Metrics/LineLength: 234 | Description: 'Limit lines to 80 characters.' 235 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#80-character-limits' 236 | Enabled: false 237 | 238 | Metrics/MethodLength: 239 | Description: 'Avoid methods longer than 30 lines of code.' 240 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods' 241 | Enabled: true 242 | Max: 30 243 | 244 | Metrics/ModuleLength: 245 | Description: 'Avoid modules longer than 250 lines of code.' 246 | Enabled: true 247 | Max: 250 248 | 249 | Metrics/ParameterLists: 250 | Description: 'Avoid parameter lists longer than three or four parameters.' 251 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#too-many-params' 252 | Enabled: true 253 | 254 | Metrics/PerceivedComplexity: 255 | Description: >- 256 | A complexity metric geared towards measuring complexity for a 257 | human reader. 258 | Enabled: false 259 | 260 | ##################### Performance ############################# 261 | 262 | Performance/Count: 263 | Description: >- 264 | Use `count` instead of `select...size`, `reject...size`, 265 | `select...count`, `reject...count`, `select...length`, 266 | and `reject...length`. 267 | Enabled: true 268 | 269 | Performance/Detect: 270 | Description: >- 271 | Use `detect` instead of `select.first`, `find_all.first`, 272 | `select.last`, and `find_all.last`. 273 | Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerabledetect-vs-enumerableselectfirst-code' 274 | Enabled: true 275 | 276 | Performance/FlatMap: 277 | Description: >- 278 | Use `Enumerable#flat_map` 279 | instead of `Enumerable#map...Array#flatten(1)` 280 | or `Enumberable#collect..Array#flatten(1)` 281 | Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablemaparrayflatten-vs-enumerableflat_map-code' 282 | Enabled: true 283 | EnabledForFlattenWithoutParams: false 284 | # If enabled, this cop will warn about usages of 285 | # `flatten` being called without any parameters. 286 | # This can be dangerous since `flat_map` will only flatten 1 level, and 287 | # `flatten` without any parameters can flatten multiple levels. 288 | 289 | Performance/ReverseEach: 290 | Description: 'Use `reverse_each` instead of `reverse.each`.' 291 | Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablereverseeach-vs-enumerablereverse_each-code' 292 | Enabled: true 293 | 294 | Performance/Sample: 295 | Description: >- 296 | Use `sample` instead of `shuffle.first`, 297 | `shuffle.last`, and `shuffle[Fixnum]`. 298 | Reference: 'https://github.com/JuanitoFatas/fast-ruby#arrayshufflefirst-vs-arraysample-code' 299 | Enabled: true 300 | 301 | Performance/Size: 302 | Description: >- 303 | Use `size` instead of `count` for counting 304 | the number of elements in `Array` and `Hash`. 305 | Reference: 'https://github.com/JuanitoFatas/fast-ruby#arraycount-vs-arraysize-code' 306 | Enabled: true 307 | 308 | Performance/StringReplacement: 309 | Description: >- 310 | Use `tr` instead of `gsub` when you are replacing the same 311 | number of characters. Use `delete` instead of `gsub` when 312 | you are deleting characters. 313 | Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringgsub-vs-stringtr-code' 314 | Enabled: true 315 | 316 | ##################### Rails ################################## 317 | 318 | Rails/ActionFilter: 319 | Description: 'Enforces consistent use of action filter methods.' 320 | Enabled: false 321 | 322 | Rails/Date: 323 | Description: >- 324 | Checks the correct usage of date aware methods, 325 | such as Date.today, Date.current etc. 326 | Enabled: false 327 | 328 | Rails/Delegate: 329 | Description: 'Prefer delegate method for delegations.' 330 | Enabled: false 331 | 332 | Rails/FindBy: 333 | Description: 'Prefer find_by over where.first.' 334 | Enabled: false 335 | 336 | Rails/FindEach: 337 | Description: 'Prefer all.find_each over all.find.' 338 | Enabled: false 339 | 340 | Rails/HasAndBelongsToMany: 341 | Description: 'Prefer has_many :through to has_and_belongs_to_many.' 342 | Enabled: false 343 | 344 | Rails/Output: 345 | Description: 'Checks for calls to puts, print, etc.' 346 | Enabled: false 347 | 348 | Rails/ReadWriteAttribute: 349 | Description: >- 350 | Checks for read_attribute(:attr) and 351 | write_attribute(:attr, val). 352 | Enabled: false 353 | 354 | Rails/ScopeArgs: 355 | Description: 'Checks the arguments of ActiveRecord scopes.' 356 | Enabled: false 357 | 358 | Rails/TimeZone: 359 | Description: 'Checks the correct usage of time zone aware methods.' 360 | StyleGuide: 'https://github.com/bbatsov/rails-style-guide#time' 361 | Reference: 'http://danilenko.org/2012/7/6/rails_timezones' 362 | Enabled: false 363 | 364 | Rails/Validation: 365 | Description: 'Use validates :attribute, hash of validations.' 366 | Enabled: false 367 | 368 | ################## Style ################################# 369 | 370 | Style/AccessModifierIndentation: 371 | Description: Check indentation of private/protected visibility modifiers. 372 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-public-private-protected' 373 | Enabled: false 374 | 375 | Style/AccessorMethodName: 376 | Description: Check the naming of accessor methods for get_/set_. 377 | Enabled: false 378 | 379 | Style/Alias: 380 | Description: 'Use alias_method instead of alias.' 381 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#alias-method' 382 | Enabled: false 383 | 384 | Style/AlignArray: 385 | Description: >- 386 | Align the elements of an array literal if they span more than 387 | one line. 388 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#align-multiline-arrays' 389 | Enabled: false 390 | 391 | Style/AlignHash: 392 | Description: >- 393 | Align the elements of a hash literal if they span more than 394 | one line. 395 | Enabled: false 396 | 397 | Style/AlignParameters: 398 | Description: >- 399 | Align the parameters of a method call if they span more 400 | than one line. 401 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-double-indent' 402 | Enabled: false 403 | 404 | Style/AndOr: 405 | Description: 'Use &&/|| instead of and/or.' 406 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-and-or-or' 407 | Enabled: false 408 | 409 | Style/ArrayJoin: 410 | Description: 'Use Array#join instead of Array#*.' 411 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#array-join' 412 | Enabled: false 413 | 414 | Style/AsciiComments: 415 | Description: 'Use only ascii symbols in comments.' 416 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-comments' 417 | Enabled: false 418 | 419 | Style/AsciiIdentifiers: 420 | Description: 'Use only ascii symbols in identifiers.' 421 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-identifiers' 422 | Enabled: false 423 | 424 | Style/Attr: 425 | Description: 'Checks for uses of Module#attr.' 426 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr' 427 | Enabled: false 428 | 429 | Style/BeginBlock: 430 | Description: 'Avoid the use of BEGIN blocks.' 431 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-BEGIN-blocks' 432 | Enabled: false 433 | 434 | Style/BarePercentLiterals: 435 | Description: 'Checks if usage of %() or %Q() matches configuration.' 436 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q-shorthand' 437 | Enabled: false 438 | 439 | Style/BlockComments: 440 | Description: 'Do not use block comments.' 441 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-block-comments' 442 | Enabled: false 443 | 444 | Style/BlockEndNewline: 445 | Description: 'Put end statement of multiline block on its own line.' 446 | Enabled: false 447 | 448 | Style/BlockDelimiters: 449 | Description: >- 450 | Avoid using {...} for multi-line blocks (multiline chaining is 451 | always ugly). 452 | Prefer {...} over do...end for single-line blocks. 453 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks' 454 | Enabled: false 455 | 456 | Style/BracesAroundHashParameters: 457 | Description: 'Enforce braces style around hash parameters.' 458 | Enabled: false 459 | 460 | Style/CaseEquality: 461 | Description: 'Avoid explicit use of the case equality operator(===).' 462 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-case-equality' 463 | Enabled: false 464 | 465 | Style/CaseIndentation: 466 | Description: 'Indentation of when in a case/when/[else/]end.' 467 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-when-to-case' 468 | Enabled: false 469 | 470 | Style/CharacterLiteral: 471 | Description: 'Checks for uses of character literals.' 472 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-character-literals' 473 | Enabled: false 474 | 475 | Style/ClassAndModuleCamelCase: 476 | Description: 'Use CamelCase for classes and modules.' 477 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#camelcase-classes' 478 | Enabled: false 479 | 480 | Style/ClassAndModuleChildren: 481 | Description: 'Checks style of children classes and modules.' 482 | Enabled: false 483 | 484 | Style/ClassCheck: 485 | Description: 'Enforces consistent use of `Object#is_a?` or `Object#kind_of?`.' 486 | Enabled: false 487 | 488 | Style/ClassMethods: 489 | Description: 'Use self when defining module/class methods.' 490 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#def-self-class-methods' 491 | Enabled: false 492 | 493 | Style/ClassVars: 494 | Description: 'Avoid the use of class variables.' 495 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-class-vars' 496 | Enabled: false 497 | 498 | Style/ClosingParenthesisIndentation: 499 | Description: 'Checks the indentation of hanging closing parentheses.' 500 | Enabled: false 501 | 502 | Style/ColonMethodCall: 503 | Description: 'Do not use :: for method call.' 504 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#double-colons' 505 | Enabled: false 506 | 507 | Style/CommandLiteral: 508 | Description: 'Use `` or %x around command literals.' 509 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-x' 510 | Enabled: false 511 | 512 | Style/CommentAnnotation: 513 | Description: 'Checks formatting of annotation comments.' 514 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#annotate-keywords' 515 | Enabled: false 516 | 517 | Style/CommentIndentation: 518 | Description: 'Indentation of comments.' 519 | Enabled: false 520 | 521 | Style/ConstantName: 522 | Description: 'Constants should use SCREAMING_SNAKE_CASE.' 523 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#screaming-snake-case' 524 | Enabled: false 525 | 526 | Style/DefWithParentheses: 527 | Description: 'Use def with parentheses when there are arguments.' 528 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens' 529 | Enabled: false 530 | 531 | Style/DeprecatedHashMethods: 532 | Description: 'Checks for use of deprecated Hash methods.' 533 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-key' 534 | Enabled: false 535 | 536 | Style/Documentation: 537 | Description: 'Document classes and non-namespace modules.' 538 | Enabled: false 539 | 540 | Style/DotPosition: 541 | Description: 'Checks the position of the dot in multi-line method calls.' 542 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains' 543 | Enabled: false 544 | 545 | Style/DoubleNegation: 546 | Description: 'Checks for uses of double negation (!!).' 547 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-bang-bang' 548 | Enabled: false 549 | 550 | Style/EachWithObject: 551 | Description: 'Prefer `each_with_object` over `inject` or `reduce`.' 552 | Enabled: false 553 | 554 | Style/ElseAlignment: 555 | Description: 'Align elses and elsifs correctly.' 556 | Enabled: false 557 | 558 | Style/EmptyElse: 559 | Description: 'Avoid empty else-clauses.' 560 | Enabled: false 561 | 562 | Style/EmptyLineBetweenDefs: 563 | Description: 'Use empty lines between defs.' 564 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#empty-lines-between-methods' 565 | Enabled: false 566 | 567 | Style/EmptyLines: 568 | Description: "Don't use several empty lines in a row." 569 | Enabled: false 570 | 571 | Style/EmptyLinesAroundAccessModifier: 572 | Description: "Keep blank lines around access modifiers." 573 | Enabled: false 574 | 575 | Style/EmptyLinesAroundBlockBody: 576 | Description: "Keeps track of empty lines around block bodies." 577 | Enabled: false 578 | 579 | Style/EmptyLinesAroundClassBody: 580 | Description: "Keeps track of empty lines around class bodies." 581 | Enabled: false 582 | 583 | Style/EmptyLinesAroundModuleBody: 584 | Description: "Keeps track of empty lines around module bodies." 585 | Enabled: false 586 | 587 | Style/EmptyLinesAroundMethodBody: 588 | Description: "Keeps track of empty lines around method bodies." 589 | Enabled: false 590 | 591 | Style/EmptyLiteral: 592 | Description: 'Prefer literals to Array.new/Hash.new/String.new.' 593 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#literal-array-hash' 594 | Enabled: false 595 | 596 | Style/EndBlock: 597 | Description: 'Avoid the use of END blocks.' 598 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-END-blocks' 599 | Enabled: false 600 | 601 | Style/EndOfLine: 602 | Description: 'Use Unix-style line endings.' 603 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#crlf' 604 | Enabled: false 605 | 606 | Style/EvenOdd: 607 | Description: 'Favor the use of Fixnum#even? && Fixnum#odd?' 608 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods' 609 | Enabled: false 610 | 611 | Style/ExtraSpacing: 612 | Description: 'Do not use unnecessary spacing.' 613 | Enabled: false 614 | 615 | Style/FileName: 616 | Description: 'Use snake_case for source file names.' 617 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files' 618 | Enabled: false 619 | 620 | Style/InitialIndentation: 621 | Description: >- 622 | Checks the indentation of the first non-blank non-comment line in a file. 623 | Enabled: false 624 | 625 | Style/FirstParameterIndentation: 626 | Description: 'Checks the indentation of the first parameter in a method call.' 627 | Enabled: false 628 | 629 | Style/FlipFlop: 630 | Description: 'Checks for flip flops' 631 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-flip-flops' 632 | Enabled: false 633 | 634 | Style/For: 635 | Description: 'Checks use of for or each in multiline loops.' 636 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-for-loops' 637 | Enabled: false 638 | 639 | Style/FormatString: 640 | Description: 'Enforce the use of Kernel#sprintf, Kernel#format or String#%.' 641 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#sprintf' 642 | Enabled: false 643 | 644 | Style/GlobalVars: 645 | Description: 'Do not introduce global variables.' 646 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#instance-vars' 647 | Reference: 'http://www.zenspider.com/Languages/Ruby/QuickRef.html' 648 | Enabled: false 649 | 650 | Style/GuardClause: 651 | Description: 'Check for conditionals that can be replaced with guard clauses' 652 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals' 653 | Enabled: false 654 | 655 | Style/HashSyntax: 656 | Description: >- 657 | Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax 658 | { :a => 1, :b => 2 }. 659 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-literals' 660 | Enabled: false 661 | 662 | Style/IfUnlessModifier: 663 | Description: >- 664 | Favor modifier if/unless usage when you have a 665 | single-line body. 666 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier' 667 | Enabled: false 668 | 669 | Style/IfWithSemicolon: 670 | Description: 'Do not use if x; .... Use the ternary operator instead.' 671 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon-ifs' 672 | Enabled: false 673 | 674 | Style/IndentationConsistency: 675 | Description: 'Keep indentation straight.' 676 | Enabled: false 677 | 678 | Style/IndentationWidth: 679 | Description: 'Use 2 spaces for indentation.' 680 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation' 681 | Enabled: false 682 | 683 | Style/IndentArray: 684 | Description: >- 685 | Checks the indentation of the first element in an array 686 | literal. 687 | Enabled: false 688 | 689 | Style/IndentHash: 690 | Description: 'Checks the indentation of the first key in a hash literal.' 691 | Enabled: false 692 | 693 | Style/InfiniteLoop: 694 | Description: 'Use Kernel#loop for infinite loops.' 695 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#infinite-loop' 696 | Enabled: false 697 | 698 | Style/Lambda: 699 | Description: 'Use the new lambda literal syntax for single-line blocks.' 700 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#lambda-multi-line' 701 | Enabled: false 702 | 703 | Style/LambdaCall: 704 | Description: 'Use lambda.call(...) instead of lambda.(...).' 705 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc-call' 706 | Enabled: false 707 | 708 | Style/LeadingCommentSpace: 709 | Description: 'Comments should start with a space.' 710 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-space' 711 | Enabled: false 712 | 713 | Style/LineEndConcatenation: 714 | Description: >- 715 | Use \ instead of + or << to concatenate two string literals at 716 | line end. 717 | Enabled: false 718 | 719 | Style/MethodCallParentheses: 720 | Description: 'Do not use parentheses for method calls with no arguments.' 721 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens' 722 | Enabled: false 723 | 724 | Style/MethodDefParentheses: 725 | Description: >- 726 | Checks if the method definitions have or don't have 727 | parentheses. 728 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens' 729 | Enabled: false 730 | 731 | Style/MethodName: 732 | Description: 'Use the configured style when naming methods.' 733 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars' 734 | Enabled: false 735 | 736 | Style/ModuleFunction: 737 | Description: 'Checks for usage of `extend self` in modules.' 738 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#module-function' 739 | Enabled: false 740 | 741 | Style/MultilineBlockChain: 742 | Description: 'Avoid multi-line chains of blocks.' 743 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks' 744 | Enabled: false 745 | 746 | Style/MultilineBlockLayout: 747 | Description: 'Ensures newlines after multiline block do statements.' 748 | Enabled: false 749 | 750 | Style/MultilineIfThen: 751 | Description: 'Do not use then for multi-line if/unless.' 752 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-then' 753 | Enabled: false 754 | 755 | Style/MultilineOperationIndentation: 756 | Description: >- 757 | Checks indentation of binary operations that span more than 758 | one line. 759 | Enabled: false 760 | 761 | Style/MultilineTernaryOperator: 762 | Description: >- 763 | Avoid multi-line ?: (the ternary operator); 764 | use if/unless instead. 765 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-multiline-ternary' 766 | Enabled: false 767 | 768 | Style/NegatedIf: 769 | Description: >- 770 | Favor unless over if for negative conditions 771 | (or control flow or). 772 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#unless-for-negatives' 773 | Enabled: false 774 | 775 | Style/NegatedWhile: 776 | Description: 'Favor until over while for negative conditions.' 777 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#until-for-negatives' 778 | Enabled: false 779 | 780 | Style/NestedTernaryOperator: 781 | Description: 'Use one expression per branch in a ternary operator.' 782 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-ternary' 783 | Enabled: false 784 | 785 | Style/Next: 786 | Description: 'Use `next` to skip iteration instead of a condition at the end.' 787 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals' 788 | Enabled: false 789 | 790 | Style/NilComparison: 791 | Description: 'Prefer x.nil? to x == nil.' 792 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods' 793 | Enabled: false 794 | 795 | Style/NonNilCheck: 796 | Description: 'Checks for redundant nil checks.' 797 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-non-nil-checks' 798 | Enabled: false 799 | 800 | Style/Not: 801 | Description: 'Use ! instead of not.' 802 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bang-not-not' 803 | Enabled: false 804 | 805 | Style/NumericLiterals: 806 | Description: >- 807 | Add underscores to large numeric literals to improve their 808 | readability. 809 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscores-in-numerics' 810 | Enabled: false 811 | 812 | Style/OneLineConditional: 813 | Description: >- 814 | Favor the ternary operator(?:) over 815 | if/then/else/end constructs. 816 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#ternary-operator' 817 | Enabled: false 818 | 819 | Style/OpMethod: 820 | Description: 'When defining binary operators, name the argument other.' 821 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#other-arg' 822 | Enabled: false 823 | 824 | Style/OptionalArguments: 825 | Description: >- 826 | Checks for optional arguments that do not appear at the end 827 | of the argument list 828 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#optional-arguments' 829 | Enabled: false 830 | 831 | Style/ParallelAssignment: 832 | Description: >- 833 | Check for simple usages of parallel assignment. 834 | It will only warn when the number of variables 835 | matches on both sides of the assignment. 836 | This also provides performance benefits 837 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parallel-assignment' 838 | Enabled: false 839 | 840 | Style/ParenthesesAroundCondition: 841 | Description: >- 842 | Don't use parentheses around the condition of an 843 | if/unless/while. 844 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-parens-if' 845 | Enabled: false 846 | 847 | Style/PercentLiteralDelimiters: 848 | Description: 'Use `%`-literal delimiters consistently' 849 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-literal-braces' 850 | Enabled: false 851 | 852 | Style/PercentQLiterals: 853 | Description: 'Checks if uses of %Q/%q match the configured preference.' 854 | Enabled: false 855 | 856 | Style/PerlBackrefs: 857 | Description: 'Avoid Perl-style regex back references.' 858 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers' 859 | Enabled: false 860 | 861 | Style/PredicateName: 862 | Description: 'Check the names of predicate methods.' 863 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark' 864 | Enabled: false 865 | 866 | Style/Proc: 867 | Description: 'Use proc instead of Proc.new.' 868 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc' 869 | Enabled: false 870 | 871 | Style/RaiseArgs: 872 | Description: 'Checks the arguments passed to raise/fail.' 873 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#exception-class-messages' 874 | Enabled: false 875 | 876 | Style/RedundantBegin: 877 | Description: "Don't use begin blocks when they are not needed." 878 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#begin-implicit' 879 | Enabled: false 880 | 881 | Style/RedundantException: 882 | Description: "Checks for an obsolete RuntimeException argument in raise/fail." 883 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-explicit-runtimeerror' 884 | Enabled: false 885 | 886 | Style/RedundantReturn: 887 | Description: "Don't use return where it's not required." 888 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-explicit-return' 889 | Enabled: false 890 | 891 | Style/RedundantSelf: 892 | Description: "Don't use self where it's not needed." 893 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-self-unless-required' 894 | Enabled: false 895 | 896 | Style/RegexpLiteral: 897 | Description: 'Use / or %r around regular expressions.' 898 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-r' 899 | Enabled: false 900 | 901 | Style/RescueEnsureAlignment: 902 | Description: 'Align rescues and ensures correctly.' 903 | Enabled: false 904 | 905 | Style/RescueModifier: 906 | Description: 'Avoid using rescue in its modifier form.' 907 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-rescue-modifiers' 908 | Enabled: false 909 | 910 | Style/SelfAssignment: 911 | Description: >- 912 | Checks for places where self-assignment shorthand should have 913 | been used. 914 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#self-assignment' 915 | Enabled: false 916 | 917 | Style/Semicolon: 918 | Description: "Don't use semicolons to terminate expressions." 919 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon' 920 | Enabled: false 921 | 922 | Style/SignalException: 923 | Description: 'Checks for proper usage of fail and raise.' 924 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#fail-method' 925 | Enabled: false 926 | 927 | Style/SingleLineBlockParams: 928 | Description: 'Enforces the names of some block params.' 929 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#reduce-blocks' 930 | Enabled: false 931 | 932 | Style/SingleLineMethods: 933 | Description: 'Avoid single-line methods.' 934 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-single-line-methods' 935 | Enabled: false 936 | 937 | Style/SpaceBeforeFirstArg: 938 | Description: >- 939 | Checks that exactly one space is used between a method name 940 | and the first argument for method calls without parentheses. 941 | Enabled: true 942 | 943 | Style/SpaceAfterColon: 944 | Description: 'Use spaces after colons.' 945 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' 946 | Enabled: false 947 | 948 | Style/SpaceAfterComma: 949 | Description: 'Use spaces after commas.' 950 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' 951 | Enabled: false 952 | 953 | Style/SpaceAroundKeyword: 954 | Description: 'Use spaces around keywords.' 955 | Enabled: false 956 | 957 | Style/SpaceAfterMethodName: 958 | Description: >- 959 | Do not put a space between a method name and the opening 960 | parenthesis in a method definition. 961 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces' 962 | Enabled: false 963 | 964 | Style/SpaceAfterNot: 965 | Description: Tracks redundant space after the ! operator. 966 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-space-bang' 967 | Enabled: false 968 | 969 | Style/SpaceAfterSemicolon: 970 | Description: 'Use spaces after semicolons.' 971 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' 972 | Enabled: false 973 | 974 | Style/SpaceBeforeBlockBraces: 975 | Description: >- 976 | Checks that the left block brace has or doesn't have space 977 | before it. 978 | Enabled: false 979 | 980 | Style/SpaceBeforeComma: 981 | Description: 'No spaces before commas.' 982 | Enabled: false 983 | 984 | Style/SpaceBeforeComment: 985 | Description: >- 986 | Checks for missing space between code and a comment on the 987 | same line. 988 | Enabled: false 989 | 990 | Style/SpaceBeforeSemicolon: 991 | Description: 'No spaces before semicolons.' 992 | Enabled: false 993 | 994 | Style/SpaceInsideBlockBraces: 995 | Description: >- 996 | Checks that block braces have or don't have surrounding space. 997 | For blocks taking parameters, checks that the left brace has 998 | or doesn't have trailing space. 999 | Enabled: false 1000 | 1001 | Style/SpaceAroundBlockParameters: 1002 | Description: 'Checks the spacing inside and after block parameters pipes.' 1003 | Enabled: false 1004 | 1005 | Style/SpaceAroundEqualsInParameterDefault: 1006 | Description: >- 1007 | Checks that the equals signs in parameter default assignments 1008 | have or don't have surrounding space depending on 1009 | configuration. 1010 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-around-equals' 1011 | Enabled: false 1012 | 1013 | Style/SpaceAroundOperators: 1014 | Description: 'Use a single space around operators.' 1015 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' 1016 | Enabled: false 1017 | 1018 | Style/SpaceInsideBrackets: 1019 | Description: 'No spaces after [ or before ].' 1020 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces' 1021 | Enabled: false 1022 | 1023 | Style/SpaceInsideHashLiteralBraces: 1024 | Description: "Use spaces inside hash literal braces - or don't." 1025 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' 1026 | Enabled: false 1027 | 1028 | Style/SpaceInsideParens: 1029 | Description: 'No spaces after ( or before ).' 1030 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces' 1031 | Enabled: false 1032 | 1033 | Style/SpaceInsideRangeLiteral: 1034 | Description: 'No spaces inside range literals.' 1035 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-space-inside-range-literals' 1036 | Enabled: false 1037 | 1038 | Style/SpaceInsideStringInterpolation: 1039 | Description: 'Checks for padding/surrounding spaces inside string interpolation.' 1040 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#string-interpolation' 1041 | Enabled: false 1042 | 1043 | Style/SpecialGlobalVars: 1044 | Description: 'Avoid Perl-style global variables.' 1045 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms' 1046 | Enabled: false 1047 | 1048 | Style/StringLiterals: 1049 | Description: 'Checks if uses of quotes match the configured preference.' 1050 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-string-literals' 1051 | Enabled: false 1052 | 1053 | Style/StringLiteralsInInterpolation: 1054 | Description: >- 1055 | Checks if uses of quotes inside expressions in interpolated 1056 | strings match the configured preference. 1057 | Enabled: false 1058 | 1059 | Style/StructInheritance: 1060 | Description: 'Checks for inheritance from Struct.new.' 1061 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-extend-struct-new' 1062 | Enabled: false 1063 | 1064 | Style/SymbolLiteral: 1065 | Description: 'Use plain symbols instead of string symbols when possible.' 1066 | Enabled: false 1067 | 1068 | Style/SymbolProc: 1069 | Description: 'Use symbols as procs instead of blocks when possible.' 1070 | Enabled: false 1071 | 1072 | Style/Tab: 1073 | Description: 'No hard tabs.' 1074 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation' 1075 | Enabled: false 1076 | 1077 | Style/TrailingBlankLines: 1078 | Description: 'Checks trailing blank lines and final newline.' 1079 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#newline-eof' 1080 | Enabled: false 1081 | 1082 | Style/TrailingCommaInArguments: 1083 | Description: 'Checks for trailing comma in parameter lists.' 1084 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-params-comma' 1085 | Enabled: false 1086 | 1087 | Style/TrailingCommaInLiteral: 1088 | Description: 'Checks for trailing comma in literals.' 1089 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas' 1090 | Enabled: false 1091 | 1092 | Style/TrailingWhitespace: 1093 | Description: 'Avoid trailing whitespace.' 1094 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace' 1095 | Enabled: false 1096 | 1097 | Style/TrivialAccessors: 1098 | Description: 'Prefer attr_* methods to trivial readers/writers.' 1099 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr_family' 1100 | Enabled: false 1101 | 1102 | Style/UnlessElse: 1103 | Description: >- 1104 | Do not use unless with else. Rewrite these with the positive 1105 | case first. 1106 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-else-with-unless' 1107 | Enabled: false 1108 | 1109 | Style/UnneededCapitalW: 1110 | Description: 'Checks for %W when interpolation is not needed.' 1111 | Enabled: false 1112 | 1113 | Style/UnneededPercentQ: 1114 | Description: 'Checks for %q/%Q when single quotes or double quotes would do.' 1115 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q' 1116 | Enabled: false 1117 | 1118 | Style/TrailingUnderscoreVariable: 1119 | Description: >- 1120 | Checks for the usage of unneeded trailing underscores at the 1121 | end of parallel variable assignment. 1122 | Enabled: false 1123 | 1124 | Style/VariableInterpolation: 1125 | Description: >- 1126 | Don't interpolate global, instance and class variables 1127 | directly in strings. 1128 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#curlies-interpolate' 1129 | Enabled: false 1130 | 1131 | Style/VariableName: 1132 | Description: 'Use the configured style when naming variables.' 1133 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars' 1134 | Enabled: false 1135 | 1136 | Style/WhenThen: 1137 | Description: 'Use when x then ... for one-line cases.' 1138 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#one-line-cases' 1139 | Enabled: false 1140 | 1141 | Style/WhileUntilDo: 1142 | Description: 'Checks for redundant do after while or until.' 1143 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-multiline-while-do' 1144 | Enabled: false 1145 | 1146 | Style/WhileUntilModifier: 1147 | Description: >- 1148 | Favor modifier while/until usage when you have a 1149 | single-line body. 1150 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#while-as-a-modifier' 1151 | Enabled: false 1152 | 1153 | Style/WordArray: 1154 | Description: 'Use %w or %W for arrays of words.' 1155 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-w' 1156 | Enabled: false 1157 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.3.0 4 | before_install: gem install bundler -v 1.11.2 5 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in json_api_responders.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | json_api_responders (2.7.0) 5 | activemodel 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | activemodel (7.0.3) 11 | activesupport (= 7.0.3) 12 | activesupport (7.0.3) 13 | concurrent-ruby (~> 1.0, >= 1.0.2) 14 | i18n (>= 1.6, < 2) 15 | minitest (>= 5.1) 16 | tzinfo (~> 2.0) 17 | byebug (11.1.3) 18 | codeclimate-test-reporter (1.0.9) 19 | simplecov (<= 0.13) 20 | coderay (1.1.3) 21 | concurrent-ruby (1.1.10) 22 | diff-lcs (1.5.0) 23 | docile (1.1.5) 24 | i18n (1.10.0) 25 | concurrent-ruby (~> 1.0) 26 | json (2.6.1) 27 | method_source (1.0.0) 28 | minitest (5.15.0) 29 | pry (0.13.1) 30 | coderay (~> 1.1) 31 | method_source (~> 1.0) 32 | pry-byebug (3.9.0) 33 | byebug (~> 11.0) 34 | pry (~> 0.13.0) 35 | rack (2.2.3) 36 | rake (10.5.0) 37 | rspec (3.11.0) 38 | rspec-core (~> 3.11.0) 39 | rspec-expectations (~> 3.11.0) 40 | rspec-mocks (~> 3.11.0) 41 | rspec-core (3.11.0) 42 | rspec-support (~> 3.11.0) 43 | rspec-expectations (3.11.0) 44 | diff-lcs (>= 1.2.0, < 2.0) 45 | rspec-support (~> 3.11.0) 46 | rspec-mocks (3.11.1) 47 | diff-lcs (>= 1.2.0, < 2.0) 48 | rspec-support (~> 3.11.0) 49 | rspec-support (3.11.0) 50 | simplecov (0.13.0) 51 | docile (~> 1.1.0) 52 | json (>= 1.8, < 3) 53 | simplecov-html (~> 0.10.0) 54 | simplecov-html (0.10.2) 55 | tzinfo (2.0.4) 56 | concurrent-ruby (~> 1.0) 57 | 58 | PLATFORMS 59 | ruby 60 | 61 | DEPENDENCIES 62 | bundler 63 | codeclimate-test-reporter 64 | json_api_responders! 65 | pry-byebug 66 | rack 67 | rake (~> 10.0) 68 | rspec 69 | simplecov 70 | 71 | BUNDLED WITH 72 | 2.3.13 73 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Infinum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JsonApiResponders 2 | 3 | [![Gem Version](https://badge.fury.io/rb/json_api_responders.svg)](https://badge.fury.io/rb/json_api_responders) 4 | [![Build Status](https://semaphoreci.com/api/v1/infinum/json_api_responders/branches/master/shields_badge.svg)](https://semaphoreci.com/infinum/json_api_responders) 5 | [![Maintainability](https://api.codeclimate.com/v1/badges/f0735e647a41336a7f0a/maintainability)](https://codeclimate.com/github/infinum/json_api_responders/maintainability) 6 | [![Test Coverage](https://api.codeclimate.com/v1/badges/f0735e647a41336a7f0a/test_coverage)](https://codeclimate.com/github/infinum/json_api_responders/test_coverage) 7 | 8 | This gem gives a few convenient methods for working with JSONAPI. It is inspired by the [responders](https://github.com/plataformatec/responders) gem. 9 | 10 | ## Installation 11 | 12 | Add this line to your application's Gemfile: 13 | 14 | ```ruby 15 | gem 'json_api_responders' 16 | ``` 17 | 18 | And then execute: 19 | 20 | $ bundle 21 | 22 | Inside your base controller, include the module: 23 | 24 | ```ruby 25 | module Api 26 | module V1 27 | class BaseController < ApplicationController 28 | include JsonApiResponders 29 | end 30 | end 31 | end 32 | ``` 33 | 34 | ## Usage 35 | 36 | This gem comes with the two following methods `respond_with` and `respond_with_error`. 37 | 38 | #### `respond_with(resource, options = {}) ` 39 | This method requires a resource as a parameter, and you can pass some options if you wish. Any options you do choose to pass into `respond_with` will be passed on to the `controller.render` method. In the [Configuration section](#configuration) you can learn how to set mandatory options. Bellow you will find a few examples on how to use this method: 40 | 41 | user = User.first 42 | respond_with user 43 | 44 | The above example will render the **User** object. 45 | 46 | user = User.first 47 | respond_with user, on_error: { 48 | : :unauthorized, detail: 'Invalid user or password' } 49 | 50 | The above example will render an **Error** response if an error would occur. 51 | 52 | #### `respond_with_error(status, detail = nil)` 53 | This method requires HTTP status code and an optional parameter explaining the error. This method will render an error message as described in the JSON API specification. Below you can see an example of how it should be used: 54 | 55 | respond_with_error(401, 'Bad credentials') 56 | respond_with_error(404, 'Not found') 57 | respond_with_error(400, 'Bad request') 58 | 59 | 60 | ## Configuration 61 | Currently you can only configure which options are required to be passed through the `respond_with` method. These required options are categorized by the controller's actions. Bellow you can find an example: 62 | 63 | # config/initializers/json_api_responders.rb 64 | JsonApiResponders.configure do |config| 65 | config.required_options = { 66 | index: [:each_serializer], 67 | create: [:serializer] 68 | } 69 | end 70 | 71 | # app/controllers/v1/users_controller.rb 72 | def create 73 | user = User.create(...) 74 | respond_with user, serializer: UserSerializer 75 | end 76 | 77 | If `:serializer` was left out of the above `respond_with` method you would see the `JsonApiResponders::Errors::RequiredOptionMissingError` be raised. 78 | 79 | ## Responses 80 | 81 | ### index 82 | 83 | render json: resource, status: 200 84 | 85 | ### show 86 | 87 | render json: resource, status: 200 88 | 89 | ### create 90 | 91 | if resource.valid? 92 | render json: resource, status: 201 93 | else 94 | render error: errors, status: 409 95 | end 96 | 97 | ### update 98 | 99 | if resource.valid? 100 | render json: resource, status: 200 101 | else 102 | render error: errors, status: 409 103 | end 104 | 105 | ### destroy 106 | 107 | head status: 204 108 | 109 | ## Error translations 110 | 111 | `json_api_responders` has translation support for error title and details. Copy & paste this file to your `config/locales` folder: 112 | 113 | ```yml 114 | en: 115 | json_api: 116 | errors: 117 | not_found: 118 | title: Not found 119 | detail: Resource not found 120 | forbidden: 121 | title: Unauthorized 122 | detail: User is not authorized to use this resource 123 | unprocessable_entity: 124 | title: Unprocessable Entity 125 | details: Cannot process request 126 | conflict: 127 | title: Invalid Attribute 128 | details: Something is missing 129 | ``` 130 | 131 | It translates using the format `I18n.t("json_api.errors.#{human_readable_status_code}.title")` 132 | 133 | ## Contributing 134 | 135 | Bug reports and pull requests are welcome on GitHub at https://github.com/infinum/json_api_responders. 136 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec 7 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "json_api_responders" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /json_api_responders.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'json_api_responders/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = 'json_api_responders' 8 | spec.version = JsonApiResponders::VERSION 9 | spec.authors = ['Stanko Krtalić Rusendić'] 10 | spec.email = ['stanko.krtalic@gmail.com'] 11 | 12 | spec.summary = 'Automatically respond to JSON::API requests' 13 | spec.description = 'Automatically respond to JSON::API requests' 14 | spec.homepage = 'https://github.com/infinum/json_api_responders' 15 | spec.license = 'MIT' 16 | 17 | if spec.respond_to?(:metadata) 18 | spec.metadata['allowed_push_host'] = 'https://rubygems.org' 19 | else 20 | raise('RubyGems 2.0 or newer is required to protect against public gem pushes.') 21 | end 22 | 23 | spec.files = `git ls-files -z`.split("\x0").reject do |f| 24 | f.match(%r{^(test|spec|features)/}) 25 | end 26 | spec.bindir = 'exe' 27 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 28 | spec.require_paths = ['lib'] 29 | 30 | spec.add_development_dependency 'bundler' 31 | spec.add_development_dependency 'rake', '~> 10.0' 32 | # spec.add_development_dependency 'rspec-rails' 33 | spec.add_development_dependency 'rspec' 34 | spec.add_development_dependency 'rack' 35 | spec.add_development_dependency 'pry-byebug' 36 | spec.add_development_dependency 'simplecov' 37 | spec.add_development_dependency 'codeclimate-test-reporter' 38 | spec.add_dependency 'activemodel' 39 | end 40 | -------------------------------------------------------------------------------- /lib/json_api_responders.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | 3 | require 'json_api_responders/version' 4 | require 'json_api_responders/errors' 5 | require 'json_api_responders/responder' 6 | require 'json_api_responders/config' 7 | 8 | module JsonApiResponders 9 | class << self 10 | attr_writer :config 11 | end 12 | 13 | def self.configure 14 | yield(config) if block_given? 15 | end 16 | 17 | def self.config 18 | @config ||= JsonApiResponders::Config.new 19 | end 20 | 21 | def self.included(base) 22 | base.rescue_from ActiveRecord::RecordNotFound, with: :record_not_found! 23 | base.rescue_from ActionController::ParameterMissing, with: :parameter_missing! 24 | end 25 | 26 | def respond_with(resource, options = {}) 27 | options = { params: params }.merge(options) 28 | JsonApiResponders.config.check_required_options(options) 29 | Responder.new(self, resource, **options).respond! 30 | end 31 | 32 | def respond_with_error(status, detail = nil) 33 | Responder.new(self, nil, on_error: { status: status, detail: detail }).respond_error 34 | end 35 | 36 | private 37 | 38 | def record_not_found!(reason) 39 | respond_with_error(:not_found, reason.message) 40 | end 41 | 42 | def parameter_missing!(reason) 43 | respond_with_error(:unprocessable_entity, reason.message) 44 | end 45 | 46 | def json_api_parse_options 47 | {} 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/json_api_responders/config.rb: -------------------------------------------------------------------------------- 1 | module JsonApiResponders 2 | class Config 3 | attr_reader :required_options 4 | DEFAULT_RENDER_METHOD = :json 5 | RENDER_METHODS = [:jsonapi, :json] 6 | 7 | def required_options=(opts = {}) 8 | @required_options = opts 9 | end 10 | 11 | def check_required_options(options) 12 | return if @required_options.nil? || @required_options.empty? 13 | action = action(options) 14 | 15 | if action && @required_options.key?(action) 16 | @required_options[action].each do |key| 17 | raise JsonApiResponders::Errors::RequiredOptionMissingError, key unless options.key? key 18 | end 19 | end 20 | end 21 | 22 | def render_method 23 | @render_method || DEFAULT_RENDER_METHOD 24 | end 25 | 26 | def render_method=(render_method) 27 | if RENDER_METHODS.include?(render_method) 28 | @render_method = render_method 29 | else 30 | raise JsonApiResponders::Errors::InvalidRenderMethodError, render_method 31 | end 32 | end 33 | 34 | private 35 | 36 | def action(options) 37 | options[:params][:action].to_sym if action_present?(options) 38 | end 39 | 40 | def action_present?(options) 41 | !options[:params].nil? && 42 | !options[:params].empty? && 43 | !options[:params][:action].nil? && 44 | !options[:params][:action].empty? 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/json_api_responders/errors.rb: -------------------------------------------------------------------------------- 1 | module JsonApiResponders 2 | module Errors 3 | class UnknownHTTPStatus < StandardError 4 | attr_reader :status 5 | 6 | def initialize(status) 7 | @status = status 8 | super(message) 9 | end 10 | 11 | def message 12 | status_symbols = 13 | Rack::Utils::SYMBOL_TO_STATUS_CODE.keys.map(&:to_s) 14 | status_codes = 15 | Rack::Utils::SYMBOL_TO_STATUS_CODE.invert.keys.map(&:to_s) 16 | statuses = (status_symbols + status_codes).join(', ') 17 | 18 | "Unknown HTTP status code '#{status}'.\n"\ 19 | "Available status codes and symbols are: #{statuses}" 20 | end 21 | end 22 | 23 | class RequiredOptionMissingError < StandardError 24 | attr_reader :required_option 25 | 26 | def initialize(required_option) 27 | @required_option = required_option 28 | super(message) 29 | end 30 | 31 | def message 32 | "Option '#{required_option}' is missing." 33 | end 34 | end 35 | 36 | class InvalidRenderMethodError < StandardError 37 | attr_reader :render_method 38 | 39 | def initialize(render_method) 40 | @render_method = render_method 41 | super(message) 42 | end 43 | 44 | def message 45 | "#{render_method} render method is invalid, must be one of: #{JsonApiResponders::Config::RENDER_METHODS}" 46 | end 47 | end 48 | 49 | class UnknownAction < StandardError 50 | attr_reader :action 51 | 52 | def initialize(action) 53 | @action = action 54 | super(message) 55 | end 56 | 57 | def message 58 | "Unknown controller action '#{action}'.\n"\ 59 | "Accepted actions are #{JsonApiResponders::Responder::ACTIONS.join(', ')}" 60 | end 61 | end 62 | 63 | class StatusNotDefined < StandardError 64 | def message 65 | 'Status is not defined' 66 | end 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/json_api_responders/responder.rb: -------------------------------------------------------------------------------- 1 | require 'json_api_responders/responder/actions' 2 | require 'json_api_responders/responder/sanitizers' 3 | 4 | module JsonApiResponders 5 | class Responder 6 | include Actions 7 | 8 | attr_accessor :options 9 | attr_reader :resource 10 | attr_reader :controller 11 | 12 | def initialize(controller, resource = nil, options = {}) 13 | @controller = controller 14 | @resource = resource 15 | @options = options 16 | end 17 | 18 | def respond! 19 | return send("respond_to_#{action}_action") if ACTIONS.include?(action) 20 | raise JsonApiResponders::Errors::UnknownAction, action 21 | end 22 | 23 | def respond_error 24 | render_error 25 | end 26 | 27 | def status 28 | return nil if @options[:status].nil? 29 | Sanitizers.status(@options[:status]) 30 | end 31 | 32 | def status=(status) 33 | @options[:status] = status 34 | end 35 | 36 | private 37 | 38 | def render_error 39 | controller.render( 40 | **render_options.merge( 41 | json: error_render_options, 42 | status: error_status 43 | ) 44 | ) 45 | end 46 | 47 | def error_status 48 | return Sanitizers.status(on_error(:status)) if on_error(:status) 49 | status 50 | end 51 | 52 | def action 53 | @options[:params][:action] 54 | end 55 | 56 | def render_options 57 | { 58 | status: status, 59 | content_type: 'application/vnd.api+json' 60 | } 61 | end 62 | 63 | def error_render_options 64 | errors = { errors: [] } 65 | 66 | errors[:errors] << { detail: on_error(:detail) } if on_error(:detail) 67 | 68 | if resource.respond_to?(:errors) 69 | if ::ActiveModel.version >= Gem::Version.new("6.1") 70 | resource.errors.each do |error| 71 | errors[:errors] << error_response(error.attribute, error.message) 72 | end 73 | else 74 | resource.errors.each do |attribute, message| 75 | errors[:errors] << error_response(attribute, message) 76 | end 77 | end 78 | end 79 | 80 | errors 81 | end 82 | 83 | def error_response(attribute, message) 84 | { 85 | title: I18n.t("json_api.errors.#{status}.title"), 86 | detail: resource.errors.full_message(attribute, message), 87 | source: { parameter: attribute, pointer: "data/attributes/#{attribute}" } 88 | } 89 | end 90 | 91 | def on_error(key) 92 | @options.fetch(:on_error, {}).fetch(key, nil) 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /lib/json_api_responders/responder/actions.rb: -------------------------------------------------------------------------------- 1 | module JsonApiResponders 2 | class Responder 3 | module Actions 4 | ACTIONS = %w(index show create update destroy).freeze 5 | 6 | def respond_to_index_action 7 | self.status ||= :ok 8 | render_resource 9 | end 10 | 11 | def respond_to_show_action 12 | self.status ||= :ok 13 | render_resource 14 | end 15 | 16 | def respond_to_create_action 17 | if has_errors? 18 | self.status ||= :unprocessable_entity 19 | render_error 20 | else 21 | self.status ||= :created 22 | render_resource 23 | end 24 | end 25 | 26 | def respond_to_update_action 27 | if has_errors? 28 | self.status ||= :unprocessable_entity 29 | render_error 30 | else 31 | self.status ||= :ok 32 | render_resource 33 | end 34 | end 35 | 36 | def respond_to_destroy_action 37 | self.status ||= :no_content 38 | controller.head(status, **render_options) 39 | end 40 | 41 | def render_resource 42 | controller.render(resource_render_options) 43 | end 44 | 45 | def resource_render_options 46 | render_options.merge(Hash[render_method, resource].merge(**options)) 47 | end 48 | 49 | private 50 | 51 | def has_errors? 52 | resource.respond_to?(:errors) && resource.errors.any? 53 | end 54 | 55 | def render_method 56 | JsonApiResponders.config.render_method 57 | end 58 | 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/json_api_responders/responder/sanitizers.rb: -------------------------------------------------------------------------------- 1 | module JsonApiResponders 2 | class Responder 3 | module Sanitizers 4 | def self.status(status) 5 | if status.is_a?(Integer) 6 | status = Rack::Utils::SYMBOL_TO_STATUS_CODE.invert[status] 7 | end 8 | 9 | if status.nil? || !status.is_a?(Symbol) || 10 | Rack::Utils::SYMBOL_TO_STATUS_CODE[status].nil? 11 | raise(Errors::UnknownHTTPStatus, status) 12 | end 13 | 14 | status 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/json_api_responders/version.rb: -------------------------------------------------------------------------------- 1 | module JsonApiResponders 2 | MAJOR = 2 3 | MINOR = 7 4 | PATCH = 1 5 | VERSION = [MAJOR, MINOR, PATCH].join('.').freeze 6 | end 7 | -------------------------------------------------------------------------------- /spec/json_api_responders_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe JsonApiResponders do 4 | it 'has a version number' do 5 | expect(JsonApiResponders::VERSION).not_to be nil 6 | end 7 | 8 | it 'does something useful' do 9 | expect(true).to eq(true) 10 | # FIX'D 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /spec/lib/json_api_responders/config/config_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | describe JsonApiResponders::Config do 3 | let(:config) { JsonApiResponders.config } 4 | 5 | context 'when config render method is not set' do 6 | after { clear_config } 7 | it 'render_method is set to default render method' do 8 | expect(config.render_method).to eq JsonApiResponders::Config::DEFAULT_RENDER_METHOD 9 | end 10 | end 11 | 12 | context 'when config render method is :jsonapi' do 13 | before do 14 | JsonApiResponders.configure do |config| 15 | config.render_method = :jsonapi 16 | end 17 | end 18 | after { clear_config } 19 | 20 | it 'render_method is set to :jsonapi' do 21 | expect(config.render_method).to eq :jsonapi 22 | end 23 | 24 | end 25 | 26 | context 'when config render method is :invalid' do 27 | after { clear_config } 28 | subject do 29 | JsonApiResponders.configure do |config| 30 | config.render_method = :invalid_render_method 31 | end 32 | end 33 | 34 | it 'raises an error' do 35 | expect{ subject }.to raise_error(JsonApiResponders::Errors::InvalidRenderMethodError) 36 | end 37 | end 38 | 39 | private 40 | 41 | def clear_config 42 | JsonApiResponders.instance_variable_set(:@config, nil) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/lib/json_api_responders/responder/actions_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe JsonApiResponders::Responder do 4 | let(:controller) { FakeController.new } 5 | let(:resource) { FakeModel.new } 6 | let(:responder) do 7 | JsonApiResponders::Responder.new(controller, resource, params: { action: action }) 8 | end 9 | let(:options) do 10 | { status: status, content_type: 'application/vnd.api+json', 11 | json: resource, params: { action: action } } 12 | end 13 | let(:error_options) do 14 | { 15 | status: status, content_type: 'application/vnd.api+json', 16 | json: { 17 | errors: [ 18 | { 19 | title: 'json_api.errors.unprocessable_entity.title', 20 | detail: "Name can't be blank", 21 | source: { parameter: :name, pointer: 'data/attributes/name' } 22 | } 23 | ] 24 | } 25 | } 26 | end 27 | 28 | context 'default configuration' do 29 | describe '#respond_to_index_action' do 30 | let(:action) { 'index' } 31 | let(:status) { :ok } 32 | 33 | it 'renders ok' do 34 | expect(controller).to receive(:render).with(options) 35 | responder.respond! 36 | end 37 | end 38 | 39 | describe '#respond_to_show_action' do 40 | let(:action) { 'show' } 41 | let(:status) { :ok } 42 | 43 | it 'renders ok' do 44 | expect(controller).to receive(:render).with(options) 45 | responder.respond! 46 | end 47 | end 48 | 49 | describe '#respond_to_create_action' do 50 | let(:action) { 'create' } 51 | 52 | context 'when resource valid' do 53 | let(:status) { :created } 54 | 55 | it 'renders created' do 56 | allow(resource).to receive_message_chain(:errors, any?: false) 57 | expect(controller).to receive(:render).with(options) 58 | responder.respond! 59 | end 60 | end 61 | 62 | context 'when resource invalid' do 63 | let(:status) { :unprocessable_entity } 64 | 65 | it 'renders unprocessable_entity' do 66 | expect(controller).to receive(:render).with(error_options) 67 | responder.respond! 68 | end 69 | end 70 | end 71 | 72 | describe '#respond_to_update_action' do 73 | let(:action) { 'update' } 74 | 75 | context 'when resource valid' do 76 | let(:status) { :ok } 77 | 78 | it 'renders ok' do 79 | allow(resource).to receive_message_chain(:errors, any?: false) 80 | expect(controller).to receive(:render).with(options) 81 | responder.respond! 82 | end 83 | end 84 | 85 | context 'when resource invalid' do 86 | let(:status) { :unprocessable_entity } 87 | 88 | it 'renders unprocessable_entity' do 89 | expect(controller).to receive(:render).with(error_options) 90 | responder.respond! 91 | end 92 | end 93 | end 94 | 95 | describe '#respond_to_destroy_action' do 96 | let(:action) { 'destroy' } 97 | let(:status) { :no_content } 98 | 99 | it 'renders no_content' do 100 | expect(controller).to receive(:head).with(status, status: :no_content, content_type: 'application/vnd.api+json') 101 | responder.respond! 102 | end 103 | end 104 | end 105 | 106 | context 'jsonapi configuration' do 107 | let(:options) do 108 | { status: status, content_type: 'application/vnd.api+json', 109 | jsonapi: resource, params: { action: action } } 110 | end 111 | 112 | before do 113 | JsonApiResponders.configure do |config| 114 | config.render_method = :jsonapi 115 | end 116 | end 117 | 118 | describe '#respond_to_index_action' do 119 | let(:action) { 'index' } 120 | let(:status) { :ok } 121 | 122 | it 'renders ok' do 123 | expect(controller).to receive(:render).with(options) 124 | responder.respond! 125 | end 126 | end 127 | 128 | describe '#respond_to_show_action' do 129 | let(:action) { 'show' } 130 | let(:status) { :ok } 131 | 132 | it 'renders ok' do 133 | expect(controller).to receive(:render).with(options) 134 | responder.respond! 135 | end 136 | end 137 | 138 | describe '#respond_to_create_action' do 139 | let(:action) { 'create' } 140 | 141 | context 'when resource valid' do 142 | let(:status) { :created } 143 | 144 | it 'renders created' do 145 | allow(resource).to receive_message_chain(:errors, any?: false) 146 | expect(controller).to receive(:render).with(options) 147 | responder.respond! 148 | end 149 | end 150 | 151 | context 'when resource invalid' do 152 | let(:status) { :unprocessable_entity } 153 | 154 | it 'renders unprocessable_entity' do 155 | expect(controller).to receive(:render).with(error_options) 156 | responder.respond! 157 | end 158 | end 159 | end 160 | 161 | describe '#respond_to_update_action' do 162 | let(:action) { 'update' } 163 | 164 | context 'when resource valid' do 165 | let(:status) { :ok } 166 | 167 | it 'renders ok' do 168 | allow(resource).to receive_message_chain(:errors, any?: false) 169 | expect(controller).to receive(:render).with(options) 170 | responder.respond! 171 | end 172 | end 173 | 174 | context 'when resource invalid' do 175 | let(:status) { :unprocessable_entity } 176 | 177 | it 'renders unprocessable_entity' do 178 | expect(controller).to receive(:render).with(error_options) 179 | responder.respond! 180 | end 181 | end 182 | end 183 | 184 | describe '#respond_to_destroy_action' do 185 | let(:action) { 'destroy' } 186 | let(:status) { :no_content } 187 | 188 | it 'renders no_content' do 189 | expect(controller).to receive(:head).with(status, status: :no_content, content_type: 'application/vnd.api+json') 190 | responder.respond! 191 | end 192 | end 193 | end 194 | end 195 | -------------------------------------------------------------------------------- /spec/lib/json_api_responders/responder_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe JsonApiResponders::Responder do 4 | let(:controller) { FakeController.new } 5 | let(:resource) { FakeModel.new } 6 | let(:responder) do 7 | JsonApiResponders::Responder.new(controller, resource, params: { action: 'index' }) 8 | end 9 | 10 | describe '#respond!' do 11 | it 'calls respond to action' do 12 | expect(responder).to receive(:respond_to_index_action) 13 | responder.respond! 14 | end 15 | 16 | it 'raises error if unknown action' do 17 | responder.options = { params: { action: 'fake' } } 18 | expect { responder.respond! }.to raise_error(JsonApiResponders::Errors::UnknownAction) 19 | end 20 | end 21 | 22 | describe '#respond_error' do 23 | it 'calls render action' do 24 | expect(responder).to receive(:render_error) 25 | responder.respond_error 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/lib/json_api_responders_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe JsonApiResponders do 4 | let(:controller) { FakeController.new } 5 | let(:resource) { FakeModel.new } 6 | let(:responder) { double(:responder) } 7 | 8 | describe '#respond_with' do 9 | it 'calls responder' do 10 | expect(JsonApiResponders::Responder).to( 11 | receive(:new).with(controller, resource, params: {}).and_return(responder) 12 | ) 13 | expect(responder).to receive(:respond!) 14 | controller.respond_with(resource) 15 | end 16 | 17 | context 'when config has required params' do 18 | before do 19 | JsonApiResponders.configure do |config| 20 | config.required_options = { create: [:foo], index: [:blah] } 21 | end 22 | end 23 | 24 | it 'calls responder' do 25 | expect(JsonApiResponders::Responder).to( 26 | receive(:new).with(controller, resource, params: { action: 'create' }, foo: :bar).and_return(responder) 27 | ) 28 | expect(responder).to receive(:respond!) 29 | controller.respond_with(resource, foo: :bar, params: { action: 'create' }) 30 | end 31 | 32 | it 'calls responder and raises error' do 33 | expect{ controller.respond_with(resource, params: { action: 'create' }) }.to raise_error(JsonApiResponders::Errors::RequiredOptionMissingError) 34 | end 35 | end 36 | 37 | context 'when resource invalid and on_error is passed' do 38 | before do 39 | JsonApiResponders.configure do |config| 40 | config.required_options = [] 41 | end 42 | end 43 | it 'calls responder' do 44 | expect(controller).to receive(:render).with( 45 | status: :unauthorized, 46 | content_type: 'application/vnd.api+json', 47 | json: { errors: [ 48 | { detail: 'Unauthorized' }, 49 | { title: 'json_api.errors.unprocessable_entity.title', 50 | detail: "Name can't be blank", 51 | source: { parameter: :name, pointer: 'data/attributes/name' } } 52 | ] } 53 | ) 54 | controller.respond_with( 55 | resource, 56 | on_error: { status: 401, detail: 'Unauthorized' }, 57 | params: { action: 'create' } 58 | ) 59 | end 60 | end 61 | end 62 | 63 | describe '#respond_with_error' do 64 | it 'calls responder with on_error' do 65 | expect(JsonApiResponders::Responder).to( 66 | receive(:new).with( 67 | controller, nil, on_error: { status: :forbidden, detail: 'help me' } 68 | ).and_return(responder) 69 | ) 70 | expect(responder).to receive(:respond_error) 71 | controller.respond_with_error(:forbidden, 'help me') 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | SimpleCov.start 3 | 4 | $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) 5 | 6 | require 'rspec' 7 | require 'rack' 8 | require 'json_api_responders' 9 | require 'pry' 10 | 11 | Dir['./spec/support/**/*.rb'].each { |f| require f } 12 | -------------------------------------------------------------------------------- /spec/support/fake_classes.rb: -------------------------------------------------------------------------------- 1 | module ActiveRecord 2 | class RecordNotFound < StandardError 3 | end 4 | end 5 | 6 | module ActionController 7 | class ParameterMissing 8 | end 9 | end 10 | 11 | class FakeController 12 | def self.rescue_from(*_args) 13 | end 14 | 15 | include JsonApiResponders 16 | 17 | def params 18 | {} 19 | end 20 | end 21 | 22 | class FakeModel 23 | include ActiveModel::Model 24 | 25 | def errors 26 | @errors ||= super.tap do |errors| 27 | errors.add(:name, "can't be blank") 28 | end 29 | end 30 | end 31 | 32 | module I18n 33 | def self.t(translation, *args) 34 | translation 35 | end 36 | end 37 | 38 | module ActiveModel 39 | class Errors 40 | def full_message(attribute, message) 41 | "#{attribute.to_s.humanize} #{message}" 42 | end 43 | end 44 | end 45 | --------------------------------------------------------------------------------