napa 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e880773f7d012f8c314fd0d58baf8b321cc0970d
4
- data.tar.gz: 0610b2934b4e1edc1a72a0f60883b116240a1f3c
3
+ metadata.gz: 99dd7c64867542bf20e480334250d1e47c271df0
4
+ data.tar.gz: 870471e9345f770dea420b9f0edf609dbf16cd25
5
5
  SHA512:
6
- metadata.gz: 15a72bf0f710f598bb027068fe1e9724fd8a21c5e11eae46e1656d4ac051b48dbe82aeae35b2725c1b3d1a4cf1a5692d5f92bc6732d3be3e34457ec563cce99b
7
- data.tar.gz: bafddb18590875dc3439383d62fc2d1974aadef74c4debd94937add6e9786370c69b2c39d0d0ebb2b6df5318a8cf766aba94cb9de532b91c6a89aaf7f5c9ed98
6
+ metadata.gz: ad6d3c13701b0536aaf9269e424b33ab91fb7e0cbd89b0d7e7e9b1cc8a080282fcd9a869e7161a6ebebe1f5839fe052c3087b34a9ca49444e42e832811380cc1
7
+ data.tar.gz: f46a872779294f28648f2f041850d46535146b763def899ac6dfebaaa9332984d654c67fae599b6ab978a0da6ebe279b057943cb900d7ef6815a75a21c1fa2fa
data/.travis.yml CHANGED
@@ -7,3 +7,7 @@ rvm:
7
7
  - ruby-2.0.0
8
8
 
9
9
  script: "bundle exec rspec spec --color"
10
+
11
+ addons:
12
+ code_climate:
13
+ repo_token: 8d11efee
data/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  master
2
2
  ===
3
+ * Added a reasons object to error responses to represent active record validation errors for individual attributes
4
+ * Added ability to filter sensitive data from logs.
3
5
 
4
6
  0.4.0
5
7
  ===
@@ -13,7 +15,7 @@ master
13
15
  * Added initialization hook to run code when a Napa service boots
14
16
  * Added Migration generators from Rails
15
17
  * Added rake db:seed functionality
16
- * Added some convinience methods to spec_helper
18
+ * Added some convenience methods to spec_helper
17
19
 
18
20
  0.3.0
19
21
  ===
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  [![Build Status](https://travis-ci.org/bellycard/napa.png?branch=master)](https://travis-ci.org/bellycard/napa)
2
2
  [![Dependency Status](https://gemnasium.com/bellycard/napa.png)](https://gemnasium.com/bellycard/napa)
3
+ [![Code Climate](https://codeclimate.com/github/bellycard/napa/badges/gpa.svg)](https://codeclimate.com/github/bellycard/napa)
4
+ [![Test Coverage](https://codeclimate.com/github/bellycard/napa/badges/coverage.svg)](https://codeclimate.com/github/bellycard/napa)
3
5
 
4
6
  # Napa
5
7
 
@@ -47,7 +49,7 @@ Commands:
47
49
 
48
50
 
49
51
  ### Console
50
- Similar to the Rails console, load an IRB sesson with your applications environment by running:
52
+ Similar to the Rails console, load an IRB session with your applications environment by running:
51
53
 
52
54
  ```
53
55
  napa console
@@ -127,6 +129,27 @@ ActiveRecord::Base.logger = Napa::Logger.logger
127
129
  ```ruby
128
130
  Napa::Logger.logger.debug 'Some Debug Message'
129
131
  ```
132
+
133
+ ### Scrubbing Logs of Sensitive Data
134
+
135
+ Some requests may contain sensitive information, such as passwords or credit card numbers. In order to protect this information, they should be filtered out from logs.
136
+
137
+ To do so, add the following line to an initializer:
138
+ ```ruby
139
+ Napa::ParamSanitizer.filter_params = [:password, :password_confirmation, :cvv, :card_number]
140
+ ```
141
+ Note that the keys in the array above are just examples. They should be replaced with the parameters that have sensitive data in their value.
142
+
143
+ Example **unfiltered** request ( ... denotes other information):
144
+ ```
145
+ { ... "message":{"request":{"method":"POST","path":"/example","query":"name=Test%20User%200039\u0026password=password", ... "params":{"name":"Test User 0039","password":"password"} ...}}}
146
+ ```
147
+
148
+ Example **filtered** request ( ... denotes other information):
149
+ ```
150
+ { ... "message":{"request":{"method":"POST","path":"/example","query":"name=Test%20User%200039\u0026password=[FILTERED]", ... "params":{"name":"Test User 0039","password":"[FILTERED]"} ...}}}
151
+ ```
152
+
130
153
  ### StatsD
131
154
  There are two middlewares available to enable StatsD reporting, `RequestStats` and `DatabaseStats`. They can be enabled independently in your `config.ru` file:
132
155
 
@@ -168,6 +191,20 @@ By default it will use `:memory_store`, but you can override it to use any other
168
191
  Napa.cache = :dalli_store
169
192
  ```
170
193
 
194
+ ### Sorting
195
+
196
+ Napa has an optional module you can include in any Api called
197
+ `Napa::SortableApi`. To include this, add `include SortableApi` in the
198
+ `helpers` block of the Api.
199
+
200
+ `SortableApi` takes in a parameter for sort in the format of
201
+ `field1,field2,-field3`, where `field1` and `field2` are used to sort
202
+ ascending, and `field3` is sorted descending. For example,
203
+ `-field4,field1` would be equivalent to `ORDER BY field4 DESC, field1'.
204
+
205
+ Call `sorted_from_params(ar_relation, params[:sort])` passing in an
206
+ `ActiveRecord::Relation` for `ar_relation`, and a comma-delimited string of field names for `params[:sort]`.
207
+
171
208
  ## Bugs & Feature Requests
172
209
  Please add an issue in [Github](https://github.com/bellycard/napa/issues) if you discover a bug or have a feature request.
173
210
 
@@ -11,6 +11,15 @@ module Napa
11
11
  rack_response(err.to_json, 404)
12
12
  end
13
13
  modified_class.rescue_from ::ActiveRecord::RecordInvalid do |e|
14
+ err = Napa::JsonError.new(:unprocessable_entity, e.message, e.record.errors.messages)
15
+ Napa::Logger.logger.debug Napa::Logger.response(422, {}, err)
16
+ rack_response(err.to_json, 422)
17
+ end
18
+ end
19
+
20
+ # if AASM is being used, rescue from invalid transitions
21
+ if defined?(::AASM)
22
+ modified_class.rescue_from ::AASM::InvalidTransition do |e|
14
23
  err = Napa::JsonError.new(:unprocessable_entity, e.message)
15
24
  Napa::Logger.logger.debug Napa::Logger.response(422, {}, err)
16
25
  rack_response(err.to_json, 422)
@@ -10,8 +10,8 @@ module Napa
10
10
  end
11
11
  end
12
12
 
13
- def present_error(code, message = '')
14
- Napa::JsonError.new(code, message)
13
+ def present_error(code, message = '', reasons={})
14
+ Napa::JsonError.new(code, message, reasons)
15
15
  end
16
16
 
17
17
  def permitted_params(options = {})
@@ -1,8 +1,9 @@
1
1
  module Napa
2
2
  class JsonError
3
- def initialize(code, message)
3
+ def initialize(code, message, reasons={})
4
4
  @code = code
5
5
  @message = message
6
+ @reasons = reasons
6
7
  end
7
8
 
8
9
  def to_json(options = {})
@@ -10,12 +11,14 @@ module Napa
10
11
  end
11
12
 
12
13
  def to_h
13
- {
14
+ e = {
14
15
  error: {
15
16
  code: @code,
16
17
  message: @message
17
18
  }
18
19
  }
20
+ e[:error][:reasons] = @reasons if @reasons.present?
21
+ e
19
22
  end
20
23
  end
21
24
  end
@@ -1,6 +1,10 @@
1
+ require 'napa/param_sanitizer'
2
+
1
3
  module Napa
2
4
  class Middleware
3
5
  class Logger
6
+ include Napa::ParamSanitizer
7
+
4
8
  def initialize(app)
5
9
  @app = app
6
10
  end
@@ -26,7 +30,8 @@ module Napa
26
30
 
27
31
  def format_request(env)
28
32
  request = Rack::Request.new(env)
29
- params = request.params
33
+ params = request.params
34
+
30
35
  begin
31
36
  params = JSON.parse(request.body.read) if env['CONTENT_TYPE'] == 'application/json'
32
37
  rescue
@@ -36,11 +41,11 @@ module Napa
36
41
  request_data = {
37
42
  method: request.request_method,
38
43
  path: request.path_info,
39
- query: request.query_string,
44
+ query: filtered_query_string(request.query_string),
40
45
  host: Napa::Identity.hostname,
41
46
  pid: Napa::Identity.pid,
42
47
  revision: Napa::Identity.revision,
43
- params: params,
48
+ params: filtered_parameters(params),
44
49
  remote_ip: request.ip
45
50
  }
46
51
  request_data[:user_id] = current_user.try(:id) if defined?(current_user)
@@ -0,0 +1,30 @@
1
+ require 'action_dispatch'
2
+
3
+ module Napa
4
+ module ParamSanitizer
5
+ include ActionDispatch::Http::FilterParameters
6
+
7
+ mattr_accessor :filter_params
8
+
9
+ KV_REGEXP = '[^&;=]+'
10
+ PAIR_REGEXP = %r{(#{KV_REGEXP})=(#{KV_REGEXP})}
11
+
12
+ def filter_params
13
+ @@filter_params || []
14
+ end
15
+
16
+ def parameter_filter
17
+ parameter_filter_for(filter_params)
18
+ end
19
+
20
+ def filtered_parameters(params)
21
+ parameter_filter.filter(params)
22
+ end
23
+
24
+ def filtered_query_string(query_string)
25
+ query_string.gsub(PAIR_REGEXP) do |_|
26
+ parameter_filter.filter([[$1, $2]]).first.join("=")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ if defined?(ActiveRecord)
2
+ module Napa
3
+ module SortableApi
4
+ def sort_from_params(objects, sort_params)
5
+ return objects if sort_params.nil?
6
+
7
+ sort_fields = sort_params.split(",")
8
+ sort_fields.each do |sort_field|
9
+ sort_field = (sort_field[1..-1] + " DESC") if sort_field.start_with?("-")
10
+ objects = objects.order(sort_field)
11
+ end
12
+
13
+ return objects
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,15 +1,19 @@
1
1
  module Napa
2
2
  module StatsDTimer
3
- def report_time(timer_name)
4
- start_time = Time.now
5
- yield
6
- response_time = (Time.now - start_time) * 1000 # statsd reports timers in milliseconds
7
- Napa::Stats.emitter.timing(timer_name, response_time)
3
+ def report_time(timer_name, sample_rate: 1)
4
+ if (Time.now.to_f * 1000).to_i % sample_rate == 0
5
+ start_time = Time.now
6
+ yield
7
+ response_time = (Time.now - start_time) * 1000 # statsd reports timers in milliseconds
8
+ Napa::Stats.emitter.timing(timer_name, response_time)
9
+ else
10
+ yield
11
+ end
8
12
  end
9
13
 
10
14
  module ClassMethods
11
- def report_time(timer_name)
12
- new.report_time(timer_name) do
15
+ def report_time(timer_name, sample_rate: 1)
16
+ new.report_time(timer_name, sample_rate: sample_rate) do
13
17
  yield
14
18
  end
15
19
  end
data/lib/napa/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Napa
2
- VERSION = '0.4.0'
2
+ VERSION = '0.4.1'
3
3
 
4
4
  class Version
5
5
  class << self
data/lib/napa.rb CHANGED
@@ -32,6 +32,7 @@ require 'napa/middleware/authentication'
32
32
  require 'napa/middleware/request_stats'
33
33
  require 'napa/middleware/database_stats'
34
34
  require 'napa/authentication'
35
+ require 'napa/sortable_api'
35
36
 
36
37
  require 'napa/deprecations'
37
38
  require 'napa/deploy'
data/napa.gemspec CHANGED
@@ -5,8 +5,9 @@ Gem::Specification.new do |gem|
5
5
  gem.authors = ["Darby Frey"]
6
6
  gem.email = ["darby@bellycard.com"]
7
7
  gem.description = %q{A simple framework for building APIs with Grape}
8
- gem.summary = %q{A simple framework for building APIs with Grape}
9
- gem.homepage = ""
8
+ gem.summary = %q{A rack-based framework wrapping around the Grape REST-like framework for Ruby.}
9
+ gem.homepage = "https://tech.bellycard.com"
10
+ gem.licenses = ['MIT']
10
11
 
11
12
  gem.files = `git ls-files`.split($\)
12
13
  gem.executables << 'napa'
@@ -17,22 +18,25 @@ Gem::Specification.new do |gem|
17
18
  gem.required_ruby_version = '>= 2.0'
18
19
 
19
20
 
20
- gem.add_dependency 'rake'
21
- gem.add_dependency 'logging'
22
- gem.add_dependency 'dotenv'
23
- gem.add_dependency 'octokit'
24
- gem.add_dependency 'thor'
25
- gem.add_dependency 'virtus'
26
- gem.add_dependency 'grape'
27
- gem.add_dependency 'grape-swagger'
28
- gem.add_dependency 'roar'
29
- gem.add_dependency 'statsd-ruby'
30
- gem.add_dependency 'racksh'
31
- gem.add_dependency 'git'
21
+ gem.add_dependency 'rake', '~> 10.3'
22
+ gem.add_dependency 'logging', '~> 1.8'
23
+ gem.add_dependency 'dotenv', '~> 1.0'
24
+ gem.add_dependency 'octokit', '~> 3.5'
25
+ gem.add_dependency 'thor', '~> 0.19'
26
+ gem.add_dependency 'virtus', '~> 1.0'
27
+ gem.add_dependency 'grape', '~> 0.9'
28
+ gem.add_dependency 'grape-swagger', '~> 0.8'
29
+ gem.add_dependency 'roar', '~> 0.12'
30
+ gem.add_dependency 'statsd-ruby', '~> 1.2'
31
+ gem.add_dependency 'racksh', '~> 1.0'
32
+ gem.add_dependency 'git', '~> 1.2'
33
+ gem.add_dependency 'actionpack', '>= 3.2'
32
34
 
33
- gem.add_development_dependency 'rspec'
34
- gem.add_development_dependency 'pry'
35
- gem.add_development_dependency 'rubocop'
36
- gem.add_development_dependency 'activerecord', '~>3.2.2'
37
- gem.add_development_dependency 'sqlite3'
35
+ gem.add_development_dependency 'rspec', '~> 3.1'
36
+ gem.add_development_dependency 'pry', '~> 0.10'
37
+ gem.add_development_dependency 'rubocop', '~> 0.25'
38
+ gem.add_development_dependency 'activerecord', '~> 3.2'
39
+ gem.add_development_dependency 'sqlite3', '~> 1.3'
40
+ gem.add_development_dependency 'acts_as_fu', '~> 0'
41
+ gem.add_development_dependency 'codeclimate-test-reporter'
38
42
  end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'rack/test'
3
+
4
+ describe Napa::GrapeExtenders do
5
+ include Rack::Test::Methods
6
+
7
+ before do
8
+ allow(Napa::Logger.logger).to receive(:debug)
9
+ end
10
+
11
+ subject do
12
+ Class.new(Grape::API) do
13
+ format :json
14
+ extend Napa::GrapeExtenders
15
+ end
16
+ end
17
+
18
+ def app
19
+ subject
20
+ end
21
+
22
+ describe 'ActiveRecord extensions' do
23
+ it 'rescues ActiveRecord::RecordNotFound and returns a 404' do
24
+ subject.get do
25
+ raise ActiveRecord::RecordNotFound
26
+ end
27
+
28
+ get '/'
29
+ expect(response_code).to be 404
30
+ expect(parsed_response.error.code).to eq 'record_not_found'
31
+ end
32
+ end
33
+
34
+ describe 'AASM extensions' do
35
+ it 'rescues AASM::InvalidTransition and returns a 422' do
36
+ module AASM
37
+ class InvalidTransition < StandardError
38
+ end
39
+ end
40
+
41
+ subject.get do
42
+ raise AASM::InvalidTransition
43
+ end
44
+
45
+ get '/'
46
+ expect(response_code).to be 422
47
+ expect(parsed_response.error.code).to eq 'unprocessable_entity'
48
+ end
49
+ end
50
+ end
@@ -10,5 +10,24 @@ describe Napa::JsonError do
10
10
  expect(parsed['error']['code']).to eq('code')
11
11
  expect(parsed['error']['message']).to eq('message')
12
12
  end
13
+
14
+ it 'returns a json hash with additional reasons' do
15
+ error = Napa::JsonError.new(:code, 'message', {foo: 'bar'}).to_json
16
+ parsed = JSON.parse(error)
17
+
18
+ expect(parsed['error']['code']).to eq('code')
19
+ expect(parsed['error']['message']).to eq('message')
20
+ expect(parsed['error']['reasons']['foo']).to eq('bar')
21
+ end
22
+
23
+ it 'excludes `reasons` from hash if no reasons given' do
24
+ error = Napa::JsonError.new(:code, 'message').to_json
25
+ parsed = JSON.parse(error)
26
+
27
+ expect(parsed['error']['code']).to eq('code')
28
+ expect(parsed['error']['message']).to eq('message')
29
+ expect(parsed['error']['reasons']).to be nil
30
+ end
31
+
13
32
  end
14
33
  end
@@ -0,0 +1,56 @@
1
+ require 'active_record'
2
+ require 'spec_helper'
3
+ require 'napa/sortable_api'
4
+
5
+ describe "SortableApi" do
6
+ describe "#sort_from_params" do
7
+ before do
8
+ build_model :foos do
9
+ integer :param1
10
+ integer :param2
11
+ end
12
+
13
+ @object1 = Foo.create(param1: 2, param2: 1)
14
+ @object2 = Foo.create(param1: 2, param2: 3)
15
+ @object3 = Foo.create(param1: 3, param2: 5)
16
+ @object4 = Foo.create(param1: 1, param2: 3)
17
+ @object5 = Foo.create(param1: 1, param2: 1)
18
+
19
+ @api = Object.new
20
+ @api.extend(Napa::SortableApi)
21
+ @foos = Foo.scoped
22
+ end
23
+
24
+ it "returns the sortable objects if sort_param is nil" do
25
+ expect(@api.sort_from_params(@foos, nil)).to eq(@foos)
26
+ end
27
+
28
+ it "sorts by a given parameter" do
29
+ sorted = @api.sort_from_params(@foos, "param1")
30
+ expect(sorted.last).to eq(@object3)
31
+ expect(sorted.to_sql).to end_with("ORDER BY param1")
32
+ end
33
+
34
+ it "sorts by a given parameter descending if preceded by -" do
35
+ sorted = @api.sort_from_params(@foos, "-param1")
36
+ expect(sorted.first).to eq(@object3)
37
+ expect(sorted.to_sql).to end_with("ORDER BY param1 DESC")
38
+ end
39
+
40
+ it "sorts by multiple parameters in order" do
41
+ sorted = @api.sort_from_params(@foos, "param2,param1")
42
+ expect(sorted.to_a).to eq([@object5, @object1, @object4, @object2, @object3])
43
+ expect(sorted.to_sql).to end_with("ORDER BY param2, param1")
44
+
45
+ alt_sorted = @api.sort_from_params(@foos, "param1,param2")
46
+ expect(alt_sorted.to_a).to eq([@object5, @object4, @object1, @object2, @object3])
47
+ expect(alt_sorted.to_sql).to end_with("ORDER BY param1, param2")
48
+ end
49
+
50
+ it "sorts by multiple parameters, even if descending" do
51
+ sorted = @api.sort_from_params(@foos, "-param2,param1")
52
+ expect(sorted.to_a).to eq([@object3, @object4, @object2, @object5, @object1])
53
+ expect(sorted.to_sql).to end_with("ORDER BY param2 DESC, param1")
54
+ end
55
+ end
56
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,16 +1,25 @@
1
1
  ENV['RACK_ENV'] = 'test'
2
2
 
3
3
  require 'napa/setup'
4
+ require 'acts_as_fu'
5
+
6
+ require "codeclimate-test-reporter"
7
+ CodeClimate::TestReporter.start
4
8
 
5
9
  Napa.skip_initialization = true
6
10
 
7
11
  require 'napa'
12
+ require 'napa/rspec_extensions/response_helpers'
8
13
 
9
14
  # from https://gist.github.com/adamstegman/926858
10
15
  RSpec.configure do |config|
16
+ config.include Napa::RspecExtensions::ResponseHelpers
17
+
11
18
  config.before(:all) { silence_output }
12
19
  config.after(:all) { enable_output }
13
20
 
21
+ config.include ActsAsFu
22
+
14
23
  config.before(:each) do
15
24
  allow(Napa).to receive(:initialize)
16
25
  allow(Napa::Logger).to receive_message_chain('logger.info').with(:napa_deprecation_warning)
metadata CHANGED
@@ -1,241 +1,283 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: napa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darby Frey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-23 00:00:00.000000000 Z
11
+ date: 2015-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '10.3'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '10.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: logging
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.8'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.8'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: dotenv
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '1.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: octokit
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '3.5'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '3.5'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: thor
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ~>
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '0.19'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ~>
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '0.19'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: virtus
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ~>
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '1.0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ~>
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '1.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: grape
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ~>
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '0.9'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ~>
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '0.9'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: grape-swagger
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ~>
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '0.8'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ~>
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '0.8'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: roar
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>='
129
+ - - ~>
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: '0.12'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>='
136
+ - - ~>
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: '0.12'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: statsd-ruby
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - '>='
143
+ - - ~>
144
144
  - !ruby/object:Gem::Version
145
- version: '0'
145
+ version: '1.2'
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - '>='
150
+ - - ~>
151
151
  - !ruby/object:Gem::Version
152
- version: '0'
152
+ version: '1.2'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: racksh
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - '>='
157
+ - - ~>
158
158
  - !ruby/object:Gem::Version
159
- version: '0'
159
+ version: '1.0'
160
160
  type: :runtime
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - '>='
164
+ - - ~>
165
165
  - !ruby/object:Gem::Version
166
- version: '0'
166
+ version: '1.0'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: git
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ~>
172
+ - !ruby/object:Gem::Version
173
+ version: '1.2'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ~>
179
+ - !ruby/object:Gem::Version
180
+ version: '1.2'
181
+ - !ruby/object:Gem::Dependency
182
+ name: actionpack
169
183
  requirement: !ruby/object:Gem::Requirement
170
184
  requirements:
171
185
  - - '>='
172
186
  - !ruby/object:Gem::Version
173
- version: '0'
187
+ version: '3.2'
174
188
  type: :runtime
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
192
  - - '>='
179
193
  - !ruby/object:Gem::Version
180
- version: '0'
194
+ version: '3.2'
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: rspec
183
197
  requirement: !ruby/object:Gem::Requirement
184
198
  requirements:
185
- - - '>='
199
+ - - ~>
186
200
  - !ruby/object:Gem::Version
187
- version: '0'
201
+ version: '3.1'
188
202
  type: :development
189
203
  prerelease: false
190
204
  version_requirements: !ruby/object:Gem::Requirement
191
205
  requirements:
192
- - - '>='
206
+ - - ~>
193
207
  - !ruby/object:Gem::Version
194
- version: '0'
208
+ version: '3.1'
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: pry
197
211
  requirement: !ruby/object:Gem::Requirement
198
212
  requirements:
199
- - - '>='
213
+ - - ~>
200
214
  - !ruby/object:Gem::Version
201
- version: '0'
215
+ version: '0.10'
202
216
  type: :development
203
217
  prerelease: false
204
218
  version_requirements: !ruby/object:Gem::Requirement
205
219
  requirements:
206
- - - '>='
220
+ - - ~>
207
221
  - !ruby/object:Gem::Version
208
- version: '0'
222
+ version: '0.10'
209
223
  - !ruby/object:Gem::Dependency
210
224
  name: rubocop
211
225
  requirement: !ruby/object:Gem::Requirement
212
226
  requirements:
213
- - - '>='
227
+ - - ~>
214
228
  - !ruby/object:Gem::Version
215
- version: '0'
229
+ version: '0.25'
216
230
  type: :development
217
231
  prerelease: false
218
232
  version_requirements: !ruby/object:Gem::Requirement
219
233
  requirements:
220
- - - '>='
234
+ - - ~>
221
235
  - !ruby/object:Gem::Version
222
- version: '0'
236
+ version: '0.25'
223
237
  - !ruby/object:Gem::Dependency
224
238
  name: activerecord
225
239
  requirement: !ruby/object:Gem::Requirement
226
240
  requirements:
227
241
  - - ~>
228
242
  - !ruby/object:Gem::Version
229
- version: 3.2.2
243
+ version: '3.2'
230
244
  type: :development
231
245
  prerelease: false
232
246
  version_requirements: !ruby/object:Gem::Requirement
233
247
  requirements:
234
248
  - - ~>
235
249
  - !ruby/object:Gem::Version
236
- version: 3.2.2
250
+ version: '3.2'
237
251
  - !ruby/object:Gem::Dependency
238
252
  name: sqlite3
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ~>
256
+ - !ruby/object:Gem::Version
257
+ version: '1.3'
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ~>
263
+ - !ruby/object:Gem::Version
264
+ version: '1.3'
265
+ - !ruby/object:Gem::Dependency
266
+ name: acts_as_fu
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - ~>
270
+ - !ruby/object:Gem::Version
271
+ version: '0'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - ~>
277
+ - !ruby/object:Gem::Version
278
+ version: '0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: codeclimate-test-reporter
239
281
  requirement: !ruby/object:Gem::Requirement
240
282
  requirements:
241
283
  - - '>='
@@ -333,8 +375,10 @@ files:
333
375
  - lib/napa/output_formatters/entity.rb
334
376
  - lib/napa/output_formatters/include_nil.rb
335
377
  - lib/napa/output_formatters/representer.rb
378
+ - lib/napa/param_sanitizer.rb
336
379
  - lib/napa/rspec_extensions/response_helpers.rb
337
380
  - lib/napa/setup.rb
381
+ - lib/napa/sortable_api.rb
338
382
  - lib/napa/stats.rb
339
383
  - lib/napa/stats_d_timer.rb
340
384
  - lib/napa/version.rb
@@ -353,6 +397,7 @@ files:
353
397
  - spec/generators/migration_generator_spec.rb
354
398
  - spec/generators/readme_generator_spec.rb
355
399
  - spec/generators/scaffold_generator_spec.rb
400
+ - spec/grape_extenders_spec.rb
356
401
  - spec/grape_extensions/error_formatter_spec.rb
357
402
  - spec/grape_extensions/include_nil_spec.rb
358
403
  - spec/identity_spec.rb
@@ -363,13 +408,15 @@ files:
363
408
  - spec/middleware/authentication_spec.rb
364
409
  - spec/middleware/database_stats_spec.rb
365
410
  - spec/middleware/request_stats_spec.rb
411
+ - spec/sortable_api_spec.rb
366
412
  - spec/spec_helper.rb
367
413
  - spec/stats_d_timer_spec.rb
368
414
  - spec/stats_spec.rb
369
415
  - spec/version_spec.rb
370
416
  - tasks/version.rake
371
- homepage: ''
372
- licenses: []
417
+ homepage: https://tech.bellycard.com
418
+ licenses:
419
+ - MIT
373
420
  metadata: {}
374
421
  post_install_message:
375
422
  rdoc_options: []
@@ -387,10 +434,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
387
434
  version: '0'
388
435
  requirements: []
389
436
  rubyforge_project:
390
- rubygems_version: 2.2.2
437
+ rubygems_version: 2.0.14
391
438
  signing_key:
392
439
  specification_version: 4
393
- summary: A simple framework for building APIs with Grape
440
+ summary: A rack-based framework wrapping around the Grape REST-like framework for
441
+ Ruby.
394
442
  test_files:
395
443
  - spec/active_record_extensions/filter_by_hash_spec.rb
396
444
  - spec/active_record_extensions/seeder_spec.rb
@@ -403,6 +451,7 @@ test_files:
403
451
  - spec/generators/migration_generator_spec.rb
404
452
  - spec/generators/readme_generator_spec.rb
405
453
  - spec/generators/scaffold_generator_spec.rb
454
+ - spec/grape_extenders_spec.rb
406
455
  - spec/grape_extensions/error_formatter_spec.rb
407
456
  - spec/grape_extensions/include_nil_spec.rb
408
457
  - spec/identity_spec.rb
@@ -413,7 +462,9 @@ test_files:
413
462
  - spec/middleware/authentication_spec.rb
414
463
  - spec/middleware/database_stats_spec.rb
415
464
  - spec/middleware/request_stats_spec.rb
465
+ - spec/sortable_api_spec.rb
416
466
  - spec/spec_helper.rb
417
467
  - spec/stats_d_timer_spec.rb
418
468
  - spec/stats_spec.rb
419
469
  - spec/version_spec.rb
470
+ has_rdoc: