onsi 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.rubocop.yml +8 -0
 - data/Gemfile.lock +1 -1
 - data/README.md +116 -2
 - data/lib/onsi/error_responder.rb +139 -0
 - data/lib/onsi/params.rb +17 -0
 - data/lib/onsi/version.rb +1 -1
 - data/lib/onsi.rb +1 -0
 - metadata +3 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: ed92bde9b8d7540e7d542621101fedc2cb414aaa07d24c751d57d7b4454b0bcb
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 441c0cd6376b4bcc6c086acb0cbec596fed03f0a190a8096e8dac639be4a28d9
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: b1b31fa4f17aad3767d5f4f2b46bf92e52ff6bd9ec7343ab4e742796d41f6791f5944b07378ec3dfd16d11b2b1caca07608fea9ad3dcb911b1a89318d8be15cd
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 4e0e591bc4fea1df9aeedc73b6f558a12e7a41b42f65a780eff24784bad73c709731af923e1fd97d0346295ff911b66584cd11e74584071f6f0bffbbef176aef
         
     | 
    
        data/.rubocop.yml
    CHANGED
    
    | 
         @@ -19,6 +19,11 @@ Metrics/ParameterLists: 
     | 
|
| 
       19 
19 
     | 
    
         
             
            Metrics/CyclomaticComplexity:
         
     | 
| 
       20 
20 
     | 
    
         
             
              Max: 10
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
      
 22 
     | 
    
         
            +
            Metrics/BlockLength:
         
     | 
| 
      
 23 
     | 
    
         
            +
              Enabled: true
         
     | 
| 
      
 24 
     | 
    
         
            +
              Exclude:
         
     | 
| 
      
 25 
     | 
    
         
            +
                - spec/**/*
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       22 
27 
     | 
    
         
             
            DotPosition:
         
     | 
| 
       23 
28 
     | 
    
         
             
              EnforcedStyle: leading
         
     | 
| 
       24 
29 
     | 
    
         | 
| 
         @@ -51,3 +56,6 @@ Style/RaiseArgs: 
     | 
|
| 
       51 
56 
     | 
    
         | 
| 
       52 
57 
     | 
    
         
             
            Style/FrozenStringLiteralComment:
         
     | 
| 
       53 
58 
     | 
    
         
             
              Enabled: false
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
            Style/IfUnlessModifier:
         
     | 
| 
      
 61 
     | 
    
         
            +
              Enabled: false
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,8 +1,8 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Onsi
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            Used to generate API responses from a  
     | 
| 
      
 3 
     | 
    
         
            +
            Used to generate API responses from a Rails App.
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 5 
     | 
    
         
            +
            ***
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            [](https://circleci.com/gh/skylarsch/onsi)
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
         @@ -10,3 +10,117 @@ Used to generate API responses from a rails App. 
     | 
|
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
            [](https://codeclimate.com/github/skylarsch/onsi/test_coverage)
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
      
 13 
     | 
    
         
            +
            ### Install
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            1. Add `gem 'onsi'` to your Gemfile
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            2. `bundle install`
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ## Getting Setup
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            ### Controllers
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            `Onsi::Controller` handles rendering resources for you.
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 26 
     | 
    
         
            +
            class PeopleController < ApplicationController
         
     | 
| 
      
 27 
     | 
    
         
            +
              include Onsi::Controller
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              # Optional. By default Onsi will render `:v1`
         
     | 
| 
      
 30 
     | 
    
         
            +
              render_version :v2
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              def show
         
     | 
| 
      
 33 
     | 
    
         
            +
                @person = Person.find(params[:id])
         
     | 
| 
      
 34 
     | 
    
         
            +
                # You can pass an Object, Enumerable, or Onsi::Resource
         
     | 
| 
      
 35 
     | 
    
         
            +
                # Whatever you pass, the object or each element in the collection *MUST*
         
     | 
| 
      
 36 
     | 
    
         
            +
                # include `Onsi::Model`
         
     | 
| 
      
 37 
     | 
    
         
            +
                render_resource @person
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
      
 40 
     | 
    
         
            +
            ```
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            ### Models
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            Used to define your API resources. Calling the class method `api_render` will
         
     | 
| 
      
 45 
     | 
    
         
            +
            allow you to begin setting up a version of your API. You're able to define as
         
     | 
| 
      
 46 
     | 
    
         
            +
            many API versions as you would like. The default rendered if nothing is
         
     | 
| 
      
 47 
     | 
    
         
            +
            specified in the `render_resource` method is `:v1`.
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 50 
     | 
    
         
            +
            class Person < ApplicationRecord
         
     | 
| 
      
 51 
     | 
    
         
            +
              include Onsi::Model
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              api_render(:v1) do
         
     | 
| 
      
 54 
     | 
    
         
            +
                # Passing the name of the attribute only will call that name as a method on
         
     | 
| 
      
 55 
     | 
    
         
            +
                # the instance of the method.
         
     | 
| 
      
 56 
     | 
    
         
            +
                attribute(:first_name)
         
     | 
| 
      
 57 
     | 
    
         
            +
                attribute(:last_name)
         
     | 
| 
      
 58 
     | 
    
         
            +
                # You can give attribute a block and it will be called on the object
         
     | 
| 
      
 59 
     | 
    
         
            +
                # instance. This lets you rename or compute attributes
         
     | 
| 
      
 60 
     | 
    
         
            +
                attribute(:full_name) { "#{first_name} #{last_name}" }
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                # Relationship requires a minimum of 2 parameters. The first is the name
         
     | 
| 
      
 63 
     | 
    
         
            +
                # of the relationship in the rendered JSON. The second is the type.
         
     | 
| 
      
 64 
     | 
    
         
            +
                # When fetching the value, Onsi will add `_id` and call that method on the
         
     | 
| 
      
 65 
     | 
    
         
            +
                # object instance. e.g. `team_id` in this case.
         
     | 
| 
      
 66 
     | 
    
         
            +
                relationship(:team, :team)
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                # Relationships can take a block that will be called on the object instance
         
     | 
| 
      
 69 
     | 
    
         
            +
                # and the return value will be used as the ID
         
     | 
| 
      
 70 
     | 
    
         
            +
                relationship(:primary_email, :email) { emails.where(primary: true).first.id }
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
| 
      
 73 
     | 
    
         
            +
            ```
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            ### Params
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            `Onsi::Params` can be used to flatten params that come into the API.
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            Calling `.parse` will give you an instance of `Onsi::Params` with whitelisted
         
     | 
| 
      
 80 
     | 
    
         
            +
            attributes & relationships. The first argument is the params from the controller.
         
     | 
| 
      
 81 
     | 
    
         
            +
            The second is an array of attributes and the third is an array of relationships.
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            Calling `#flatten` will merge the attributes & relationships.
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            ```json
         
     | 
| 
      
 86 
     | 
    
         
            +
            {
         
     | 
| 
      
 87 
     | 
    
         
            +
              "data": {
         
     | 
| 
      
 88 
     | 
    
         
            +
                "type": "person",
         
     | 
| 
      
 89 
     | 
    
         
            +
                "attributes": {
         
     | 
| 
      
 90 
     | 
    
         
            +
                  "first_name": "Skylar",
         
     | 
| 
      
 91 
     | 
    
         
            +
                  "last_name": "Schipper",
         
     | 
| 
      
 92 
     | 
    
         
            +
                  "bad_value": "'); DROP TABLE `people`; --"
         
     | 
| 
      
 93 
     | 
    
         
            +
                },
         
     | 
| 
      
 94 
     | 
    
         
            +
                "relationships": {
         
     | 
| 
      
 95 
     | 
    
         
            +
                  "team": {
         
     | 
| 
      
 96 
     | 
    
         
            +
                    "data": {
         
     | 
| 
      
 97 
     | 
    
         
            +
                      "type": "team",
         
     | 
| 
      
 98 
     | 
    
         
            +
                      "id": "1"
         
     | 
| 
      
 99 
     | 
    
         
            +
                    }
         
     | 
| 
      
 100 
     | 
    
         
            +
                  },
         
     | 
| 
      
 101 
     | 
    
         
            +
                  "unknown": {
         
     | 
| 
      
 102 
     | 
    
         
            +
                    "data": [
         
     | 
| 
      
 103 
     | 
    
         
            +
                      { "type": "foo", "id": "1" }
         
     | 
| 
      
 104 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 105 
     | 
    
         
            +
                  }
         
     | 
| 
      
 106 
     | 
    
         
            +
                }
         
     | 
| 
      
 107 
     | 
    
         
            +
              }
         
     | 
| 
      
 108 
     | 
    
         
            +
            }
         
     | 
| 
      
 109 
     | 
    
         
            +
            ```
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            Flattened gives you:
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 114 
     | 
    
         
            +
            { "first_name" => "Skylar", "last_name" => "Schipper", "team_id" => "1" }
         
     | 
| 
      
 115 
     | 
    
         
            +
            ```
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 118 
     | 
    
         
            +
            class PeopleController < ApplicationController
         
     | 
| 
      
 119 
     | 
    
         
            +
              include Onsi::Controller
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
              def create
         
     | 
| 
      
 122 
     | 
    
         
            +
                attributes = Onsi::Param.parse(params, [:first_name, :last_name], [:team])
         
     | 
| 
      
 123 
     | 
    
         
            +
                render_resource Person.create!(attributes.flatten)
         
     | 
| 
      
 124 
     | 
    
         
            +
              end
         
     | 
| 
      
 125 
     | 
    
         
            +
            end
         
     | 
| 
      
 126 
     | 
    
         
            +
            ```
         
     | 
| 
         @@ -0,0 +1,139 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'active_support/concern'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Onsi
         
     | 
| 
      
 4 
     | 
    
         
            +
              module ErrorResponder
         
     | 
| 
      
 5 
     | 
    
         
            +
                extend ActiveSupport::Concern
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                included do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  rescue_from StandardError,                         with: :render_error_500
         
     | 
| 
      
 9 
     | 
    
         
            +
                  rescue_from ActiveRecord::RecordNotFound,          with: :render_error_404
         
     | 
| 
      
 10 
     | 
    
         
            +
                  rescue_from ActiveRecord::RecordInvalid,           with: :render_error_422
         
     | 
| 
      
 11 
     | 
    
         
            +
                  rescue_from ActionController::ParameterMissing,    with: :respond_param_error_400
         
     | 
| 
      
 12 
     | 
    
         
            +
                  rescue_from Onsi::Params::MissingReqiredAttribute, with: :respond_missing_attr_error_400
         
     | 
| 
      
 13 
     | 
    
         
            +
                  rescue_from Onsi::Params::RelationshipNotFound,    with: :respond_missing_relationship_error_400
         
     | 
| 
      
 14 
     | 
    
         
            +
                  rescue_from Onsi::Errors::UnknownVersionError,     with: :respond_invalid_version_error_400
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def render_error(response)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  render(response.renderable)
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def render_error_500(error)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  notify_unhandled_exception(error)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  response = ErrorResponse.new(500)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  response.add(500, 'internal_server_error', meta: error_metadata(error))
         
     | 
| 
      
 25 
     | 
    
         
            +
                  render_error(response)
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def render_error_404(_error)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  response = ErrorResponse.new(404)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  response.add(404, 'not_found')
         
     | 
| 
      
 31 
     | 
    
         
            +
                  render_error(response)
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def render_error_422(error)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  response = ErrorResponse.new(422)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  error.record.errors.details.each do |name, details|
         
     | 
| 
      
 37 
     | 
    
         
            +
                    details.each do |info|
         
     | 
| 
      
 38 
     | 
    
         
            +
                      response.add(
         
     | 
| 
      
 39 
     | 
    
         
            +
                        422,
         
     | 
| 
      
 40 
     | 
    
         
            +
                        'validation_error',
         
     | 
| 
      
 41 
     | 
    
         
            +
                        title: "Validation Error: #{info[:error]}",
         
     | 
| 
      
 42 
     | 
    
         
            +
                        meta: info.merge(param: name)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      )
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                  render_error(response)
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def respond_param_error_400(error)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  response = ErrorResponse.new(400)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  response.add(
         
     | 
| 
      
 52 
     | 
    
         
            +
                    400,
         
     | 
| 
      
 53 
     | 
    
         
            +
                    'missing_parameter',
         
     | 
| 
      
 54 
     | 
    
         
            +
                    meta: { param: error.param }
         
     | 
| 
      
 55 
     | 
    
         
            +
                  )
         
     | 
| 
      
 56 
     | 
    
         
            +
                  render_error(response)
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def respond_missing_relationship_error_400(error)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  response = ErrorResponse.new(400)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  response.add(
         
     | 
| 
      
 62 
     | 
    
         
            +
                    400,
         
     | 
| 
      
 63 
     | 
    
         
            +
                    'missing_relationship',
         
     | 
| 
      
 64 
     | 
    
         
            +
                    meta: { param: error.key }
         
     | 
| 
      
 65 
     | 
    
         
            +
                  )
         
     | 
| 
      
 66 
     | 
    
         
            +
                  render_error(response)
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def respond_invalid_version_error_400(error)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  notify_unhandled_exception(error)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  response = ErrorResponse.new(400)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  response.add(
         
     | 
| 
      
 73 
     | 
    
         
            +
                    400,
         
     | 
| 
      
 74 
     | 
    
         
            +
                    'invalid_version',
         
     | 
| 
      
 75 
     | 
    
         
            +
                    details: "API version #{error.version} unsupported for #{error.klass.name.underscore}"
         
     | 
| 
      
 76 
     | 
    
         
            +
                  )
         
     | 
| 
      
 77 
     | 
    
         
            +
                  render_error(response)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def respond_missing_attr_error_400(error)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  response = ErrorResponse.new(400)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  response.add(
         
     | 
| 
      
 83 
     | 
    
         
            +
                    400,
         
     | 
| 
      
 84 
     | 
    
         
            +
                    'missing_attribute',
         
     | 
| 
      
 85 
     | 
    
         
            +
                    meta: {
         
     | 
| 
      
 86 
     | 
    
         
            +
                      attribute: error.attribute
         
     | 
| 
      
 87 
     | 
    
         
            +
                    }
         
     | 
| 
      
 88 
     | 
    
         
            +
                  )
         
     | 
| 
      
 89 
     | 
    
         
            +
                  render_error(response)
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                def notify_unhandled_exception(exception)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  Rails.logger.error "Unhandled Exception `#{exception.class.name}: #{exception.message}`"
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                private
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                def error_metadata(error)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  return nil unless Rails.configuration.consider_all_requests_local
         
     | 
| 
      
 100 
     | 
    
         
            +
                  {
         
     | 
| 
      
 101 
     | 
    
         
            +
                    exception: {
         
     | 
| 
      
 102 
     | 
    
         
            +
                      class: error.class.name,
         
     | 
| 
      
 103 
     | 
    
         
            +
                      message: error.message,
         
     | 
| 
      
 104 
     | 
    
         
            +
                      backtrace: error.backtrace
         
     | 
| 
      
 105 
     | 
    
         
            +
                    }
         
     | 
| 
      
 106 
     | 
    
         
            +
                  }
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
              class ErrorResponse
         
     | 
| 
      
 111 
     | 
    
         
            +
                attr_reader :status
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                def initialize(status)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  @status = status
         
     | 
| 
      
 115 
     | 
    
         
            +
                  @errors = []
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                def add(status, code, title: nil, details: nil, meta: nil)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  @errors << {}.tap do |err|
         
     | 
| 
      
 120 
     | 
    
         
            +
                    err[:status] = (status || @status).to_s
         
     | 
| 
      
 121 
     | 
    
         
            +
                    err[:code]   = code
         
     | 
| 
      
 122 
     | 
    
         
            +
                    err[:title]  = title      if title.present?
         
     | 
| 
      
 123 
     | 
    
         
            +
                    err[:detail] = details    if details.present?
         
     | 
| 
      
 124 
     | 
    
         
            +
                    err[:meta]   = Hash(meta) if meta.present?
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
                end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                def as_json
         
     | 
| 
      
 129 
     | 
    
         
            +
                  { errors: @errors.as_json }
         
     | 
| 
      
 130 
     | 
    
         
            +
                end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                def renderable
         
     | 
| 
      
 133 
     | 
    
         
            +
                  {
         
     | 
| 
      
 134 
     | 
    
         
            +
                    json:   as_json,
         
     | 
| 
      
 135 
     | 
    
         
            +
                    status: status
         
     | 
| 
      
 136 
     | 
    
         
            +
                  }
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
              end
         
     | 
| 
      
 139 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/onsi/params.rb
    CHANGED
    
    | 
         @@ -9,6 +9,15 @@ module Onsi 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  end
         
     | 
| 
       10 
10 
     | 
    
         
             
                end
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
      
 12 
     | 
    
         
            +
                class MissingReqiredAttribute < StandardError
         
     | 
| 
      
 13 
     | 
    
         
            +
                  attr_reader :attribute
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def initialize(message, attr)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    super(message)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @attribute = attr
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       12 
21 
     | 
    
         
             
                class << self
         
     | 
| 
       13 
22 
     | 
    
         
             
                  def parse(params, attributes = [], relationships = [])
         
     | 
| 
       14 
23 
     | 
    
         
             
                    data = params.require(:data)
         
     | 
| 
         @@ -63,6 +72,14 @@ module Onsi 
     | 
|
| 
       63 
72 
     | 
    
         
             
                  attributes.to_h.merge(relationships.to_h).with_indifferent_access
         
     | 
| 
       64 
73 
     | 
    
         
             
                end
         
     | 
| 
       65 
74 
     | 
    
         | 
| 
      
 75 
     | 
    
         
            +
                def require(key)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  value = attributes.to_h.with_indifferent_access[key]
         
     | 
| 
      
 77 
     | 
    
         
            +
                  if value.nil?
         
     | 
| 
      
 78 
     | 
    
         
            +
                    raise MissingReqiredAttribute.new("Missing attribute #{key}", key)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                  value
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
       66 
83 
     | 
    
         
             
                def safe_fetch(key)
         
     | 
| 
       67 
84 
     | 
    
         
             
                  yield(@relationships[key])
         
     | 
| 
       68 
85 
     | 
    
         
             
                rescue ActiveRecord::RecordNotFound
         
     | 
    
        data/lib/onsi/version.rb
    CHANGED
    
    
    
        data/lib/onsi.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: onsi
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.3.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Skylar Schipper
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2018-05- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2018-05-18 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rails
         
     | 
| 
         @@ -164,6 +164,7 @@ files: 
     | 
|
| 
       164 
164 
     | 
    
         
             
            - bin/setup
         
     | 
| 
       165 
165 
     | 
    
         
             
            - lib/onsi.rb
         
     | 
| 
       166 
166 
     | 
    
         
             
            - lib/onsi/controller.rb
         
     | 
| 
      
 167 
     | 
    
         
            +
            - lib/onsi/error_responder.rb
         
     | 
| 
       167 
168 
     | 
    
         
             
            - lib/onsi/errors.rb
         
     | 
| 
       168 
169 
     | 
    
         
             
            - lib/onsi/model.rb
         
     | 
| 
       169 
170 
     | 
    
         
             
            - lib/onsi/params.rb
         
     |