desponders 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e54fe6506dfbcfbd55b07f20c47647da2cc553bf
4
+ data.tar.gz: b0d9692bcbcceb0798ee20943ef4ed75849fa47d
5
+ SHA512:
6
+ metadata.gz: 53ff2a38c22f6b6a441eda7df9e8870febd397e978afd8736e216a15311036c11ab27d0277746767981bce161b6f636f6932a3c5d7d1eae6056c1449bd29357c
7
+ data.tar.gz: 4f80b5479461aa336fe2946ae7356413ea68a9c5893c1fd86b8d8c2e10acf1c2e0d231f7d94b0636a3fa588f7f57483b3b869e3bb256e6a3e98e5d361ebefc5b
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ bin/
12
+ vendor/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ -I spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ script: bundle exec rspec spec
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # 0.2.0
2
+
3
+ - Initial release ported from internal responders. Initial set of responders
4
+ includes:
5
+
6
+ - Error
7
+ - HttpCaching
8
+ - Paginated
9
+ - Rest
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in desponders.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Dscout, Inc
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ [![Build Status](https://travis-ci.org/dscout/desponders.png?branch=master)](https://travis-ci.org/dscout/desponders)
2
+
3
+ # Desponders
4
+
5
+ A stack of light-weight responders tailored to JSON APIs.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'desponders', '0.2.0'
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Use the provided `ApiResponder`, which includes all of the responder modules in
18
+ a sane order:
19
+
20
+ * Desponders::ErrorResponder
21
+ * Desponders::RESTResponder
22
+ * Desponders::PaginatedResponder
23
+ * Desponders::HTTPCacheResponder
24
+
25
+ Alternatively, create a `ActionController::Responder` subclass and include the
26
+ responders that you would like to use:
27
+
28
+ ```ruby
29
+ class CustomResponder < ActionController::Responder
30
+ include Desponders::RESTResponder
31
+ include Desponders::HTTPCacheResponder
32
+ end
33
+ ```
34
+
35
+ Include the responder in any controllers serving API requests:
36
+
37
+ ```ruby
38
+ class ApplicationController < ActionController::Base
39
+ # Included
40
+ self.responder = Desponder::Responder
41
+
42
+ # Custom
43
+ self.responder = CustomResponder
44
+ end
45
+ ```
46
+
47
+ ## Thanks
48
+
49
+ The implementation of Desponders is based on the fanstastic work of Jose Valim
50
+ and his contributions to Responders within Rails, as well as Plataformatec's
51
+ Responders gem.
52
+
53
+ ## Contributing
54
+
55
+ 1. Fork it
56
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
57
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
58
+ 4. Push to the branch (`git push origin my-new-feature`)
59
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'desponders/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'desponders'
8
+ spec.version = Desponders::VERSION
9
+ spec.authors = ['Parker Selbert']
10
+ spec.email = ['parker@sorentwo.com']
11
+ spec.homepage = 'https://github.com/dscout/desponders'
12
+ spec.license = 'MIT'
13
+ spec.description = 'A stack of light-weight responders tailored to JSON APIs'
14
+ spec.summary = 'A stack of light-weight responders tailored to JSON APIs'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.test_files = spec.files.grep(%r{^(spec)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_dependency 'railties', '>= 3.2', '< 5'
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.3'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'rspec', '~> 2.14.0'
25
+ end
@@ -0,0 +1,23 @@
1
+ module Desponders
2
+ module ErrorResponder
3
+ # If it isn't a get request and the response model has errors it
4
+ # automatically renders json with errors
5
+ def to_format
6
+ if has_errors?
7
+ controller.render json: {
8
+ message: lookup_message, errors: resource.errors
9
+ }, status: :unprocessable_entity
10
+ else
11
+ super
12
+ end
13
+ end
14
+
15
+ def lookup_message
16
+ action = controller.action_name
17
+ lookup = ['errors', action].join('.').to_sym
18
+ options = { resource_name: resource.class.model_name.human }
19
+
20
+ I18n.t(lookup, options)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ module Desponders
2
+ module HttpCacheResponder
3
+ def to_format
4
+ return if do_http_cache? && do_http_cache!
5
+
6
+ super
7
+ end
8
+
9
+ private
10
+
11
+ def do_http_cache?
12
+ get? && ActionController::Base.perform_caching &&
13
+ resource.respond_to?(:updated_at)
14
+ end
15
+
16
+ def do_http_cache!
17
+ controller.fresh_when(etag: resource,
18
+ last_modified: resource.updated_at,
19
+ public: false)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ en:
2
+ errors:
3
+ create: "%{resource_name} could not be created"
4
+ update: "%{resource_name} could not be updated"
5
+ destroy: "%{resource_name} could not be destroyed"
6
+
@@ -0,0 +1,69 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+
3
+ module Desponders
4
+ module PaginatedResponder
5
+ def to_format
6
+ if get? && resource.respond_to?(:paginate)
7
+ self.resource_size = resource.size
8
+ self.resource = resource.paginate(page: page, per_page: per_page)
9
+
10
+ response.headers['Link'] = link_headers
11
+ end
12
+
13
+ super
14
+ end
15
+
16
+ private
17
+
18
+ attr_accessor :resource, :resource_size
19
+
20
+ delegate :response, :request, to: :controller
21
+
22
+ def default_page
23
+ 1
24
+ end
25
+
26
+ def default_per_page
27
+ 30
28
+ end
29
+
30
+ def page
31
+ (request.params[:page] || default_page).to_i
32
+ end
33
+
34
+ def per_page
35
+ (request.params[:per_page] || default_per_page).to_i
36
+ end
37
+
38
+ def first_page
39
+ 1
40
+ end
41
+
42
+ def prev_page
43
+ [first_page, page - 1].max
44
+ end
45
+
46
+ def next_page
47
+ [last_page, page + 1].min
48
+ end
49
+
50
+ def last_page
51
+ calculated = (resource_size.to_f / per_page).ceil
52
+
53
+ calculated.zero? ? 1 : calculated
54
+ end
55
+
56
+ def link_headers
57
+ base, rest = request.url.split('?')
58
+
59
+ [construct_link_rel(base, first_page, per_page, 'first'),
60
+ construct_link_rel(base, prev_page, per_page, 'prev'),
61
+ construct_link_rel(base, next_page, per_page, 'next'),
62
+ construct_link_rel(base, last_page, per_page, 'last')].join(',')
63
+ end
64
+
65
+ def construct_link_rel(base, page, per_page, rel)
66
+ %(#{base}?page=#{page}&per_page=#{per_page}; rel="#{rel}")
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,18 @@
1
+ module Desponders
2
+ module RestResponder
3
+ def to_format
4
+ case
5
+ when get?
6
+ display(resource, status: :ok)
7
+ when has_errors?
8
+ super
9
+ when post?
10
+ display(resource, status: :created)
11
+ when put?
12
+ display(resource, status: :ok)
13
+ when delete?
14
+ display({}, status: :no_content)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Desponders
2
+ VERSION = '0.2.0'
3
+ end
data/lib/desponders.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'action_controller/base'
2
+
3
+ module Desponders
4
+ autoload :ErrorResponder, 'desponders/error_responder'
5
+ autoload :HttpCacheResponder, 'desponders/http_cache_responder'
6
+ autoload :PaginatedResponder, 'desponders/paginated_responder'
7
+ autoload :RestResponder, 'desponders/rest_responder'
8
+
9
+ class Railtie < ::Rails::Railtie
10
+ require 'active_support/i18n'
11
+ I18n.load_path << File.expand_path('../desponders/locales/en.yml', __FILE__)
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ I18n.load_path += [File.expand_path('lib/desponders/locales/en.yml')]
4
+
5
+ describe Desponders::ErrorResponder do
6
+ class MockErrorResponder < Struct.new(:to_format)
7
+ include Desponders::ErrorResponder
8
+
9
+ attr_accessor :controller, :resource
10
+
11
+ def initialize(controller, resource)
12
+ @controller = controller
13
+ @resource = resource
14
+ end
15
+ end
16
+
17
+ let(:controller) { double(:controller, action_name: 'create') }
18
+ let(:resource) { double(:resource, errors: []) }
19
+
20
+ subject(:responder) { MockErrorResponder.new(controller, resource) }
21
+
22
+ before do
23
+ resource.class.stub_chain(:model_name, :human).and_return('Mock')
24
+ end
25
+
26
+ it 'renders error messages when a non-get request has errors ' do
27
+ responder.stub(has_errors?: true)
28
+
29
+ expect(controller).to receive(:render).with(json: {
30
+ message: 'Mock could not be created',
31
+ errors: []
32
+ }, status: :unprocessable_entity)
33
+
34
+ responder.to_format
35
+ end
36
+
37
+ it 'does not render without errors' do
38
+ responder.stub(has_errors?: false)
39
+
40
+ expect(controller).to_not receive(:render)
41
+
42
+ responder.to_format
43
+ end
44
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe Desponders::HttpCacheResponder do
4
+ class MockHttpCacheResponderBase
5
+ def to_format
6
+ '{}'
7
+ end
8
+ end
9
+
10
+ class MockHttpCacheResponder < MockHttpCacheResponderBase
11
+ include Desponders::HttpCacheResponder
12
+
13
+ attr_accessor :controller
14
+
15
+ def initialize(controller)
16
+ @controller = controller
17
+ end
18
+ end
19
+
20
+ let(:controller) { double(:controller, fresh_when: true) }
21
+ let(:resource) { double(:resource, updated_at: nil) }
22
+ let(:collection) { double(:collection) }
23
+
24
+ subject(:responder) { MockHttpCacheResponder.new(controller) }
25
+
26
+ it 'returns nothing with a single resource on get' do
27
+ responder.stub(get?: true, fresh_when: true, resource: resource)
28
+
29
+ expect(responder.to_format).to be_nil
30
+ end
31
+
32
+ it 'passes through with multiple resources on get' do
33
+ responder.stub(get?: true, resource: collection)
34
+
35
+ expect(responder.to_format).to be_present
36
+ end
37
+
38
+ it 'passes through without a fresh resource' do
39
+ controller.stub(fresh_when: false)
40
+ responder.stub(get?: true, resource: resource)
41
+
42
+ expect(responder.to_format).to be_present
43
+ end
44
+
45
+ it 'passes through without a get request' do
46
+ responder.stub(get?: false, resource: resource)
47
+
48
+ expect(responder.to_format).to be_present
49
+ end
50
+
51
+ it 'does not cache if perform_caching is false' do
52
+ responder.stub(get?: true, resource: resource)
53
+
54
+ ActionController::Base.stub(perform_caching: false)
55
+
56
+ expect(responder.to_format).to be_present
57
+ end
58
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe Desponders::PaginatedResponder do
4
+ class MockPaginatedResponderBase
5
+ def to_format
6
+ end
7
+ end
8
+
9
+ class MockPaginatedResponder < MockPaginatedResponderBase
10
+ include Desponders::PaginatedResponder
11
+
12
+ attr_accessor :controller, :resource
13
+
14
+ def initialize(controller, resource)
15
+ @controller = controller
16
+ @resource = resource
17
+ end
18
+
19
+ def get?; true; end
20
+ end
21
+
22
+ let(:controller) { double(:controller, request: request, response: response) }
23
+ let(:paginated) { double(:paginated) }
24
+ let(:request) { double(:request, params: {}, url: 'https://example.com/missions') }
25
+ let(:response) { double(:response, headers: {}) }
26
+ let(:resource) { double(:resource, paginate: paginated, size: 100) }
27
+
28
+ subject(:responder) { MockPaginatedResponder.new(controller, resource) }
29
+
30
+ def link_header
31
+ controller.response.headers['Link']
32
+ end
33
+
34
+ context 'with a paginatable resource on a get request' do
35
+ it 'replaces the current resource with a paginated scope' do
36
+ responder.to_format
37
+ responder.resource.should eq(paginated)
38
+ end
39
+
40
+ it 'defaults pagination to the first page' do
41
+ resource.should_receive(:paginate).with(hash_including(page: 1))
42
+ responder.to_format
43
+ end
44
+
45
+ it 'uses provided page and per_page params' do
46
+ resource.should_receive(:paginate).with(page: 2, per_page: 25)
47
+
48
+ request.params[:page] = 2
49
+ request.params[:per_page] = 25
50
+
51
+ responder.to_format
52
+ end
53
+
54
+ it 'injects resource urls into a LINK header' do
55
+ request.params[:page] = 2
56
+
57
+ responder.to_format
58
+
59
+ link_header.tap do |header|
60
+ header.should include('https://example.com/missions?page=1&per_page=30; rel="first"')
61
+ header.should include('https://example.com/missions?page=1&per_page=30; rel="prev"')
62
+ header.should include('https://example.com/missions?page=3&per_page=30; rel="next"')
63
+ header.should include('https://example.com/missions?page=4&per_page=30; rel="last"')
64
+ end
65
+ end
66
+
67
+ it 'ignores params in the request url when constructing headers' do
68
+ request.stub(url: 'https://example.com/missions?thing=1&other=2')
69
+
70
+ responder.to_format
71
+
72
+ link_header.should_not include('?thing=1&other=2')
73
+ end
74
+
75
+ it 'calculates the next page based on resource size and the per_page value' do
76
+ resource.stub(size: 500)
77
+
78
+ request.params[:page] = 3
79
+ request.params[:per_page] = 50
80
+
81
+ responder.to_format
82
+
83
+ link_header.tap do |header|
84
+ header.should include('page=2&per_page=50; rel="prev"')
85
+ header.should include('page=4&per_page=50; rel="next"')
86
+ end
87
+ end
88
+
89
+ it 'prevents the next and last pages from being 0' do
90
+ resource.stub(size: 0)
91
+
92
+ responder.to_format
93
+
94
+ link_header.should include('page=1&per_page=30; rel="next"')
95
+ link_header.should include('page=1&per_page=30; rel="last"')
96
+ end
97
+
98
+ it 'calculates the last page based on resource size and the per_page value' do
99
+ resource.stub(size: 500)
100
+
101
+ request.params[:per_page] = 50
102
+
103
+ responder.to_format
104
+
105
+ link_header.should include('page=10&per_page=50; rel="last"')
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe Desponders::RestResponder do
4
+ class MockRestResponderBase
5
+ def to_format
6
+ '{}'
7
+ end
8
+ end
9
+
10
+ class MockRestResponder < MockRestResponderBase
11
+ include Desponders::RestResponder
12
+
13
+ attr_accessor :resource
14
+
15
+ def initialize(resource)
16
+ @resource = resource
17
+ end
18
+
19
+ def display
20
+ end
21
+
22
+ def get?; false; end
23
+ def post?; false; end
24
+ def put?; false; end
25
+ def delete?; false; end
26
+ def has_errors?; false; end
27
+ end
28
+
29
+ let(:resource) { double(:resource) }
30
+
31
+ subject(:responder) { MockRestResponder.new(resource) }
32
+
33
+ it 'renders the resource with 200 status with a get request' do
34
+ responder.stub(get?: true)
35
+
36
+ expect(responder).to receive(:display).with(resource, status: :ok)
37
+
38
+ responder.to_format
39
+ end
40
+
41
+ it 'renders the resource with 201 created with a create request' do
42
+ responder.stub(post?: true)
43
+
44
+ expect(responder).to receive(:display).with(resource, status: :created)
45
+
46
+ responder.to_format
47
+ end
48
+
49
+ it 'renders the resource with a put request' do
50
+ responder.stub(put?: true)
51
+
52
+ expect(responder).to receive(:display).with(resource, status: :ok)
53
+
54
+ responder.to_format
55
+ end
56
+
57
+ it 'renders no content with a delete request' do
58
+ responder.stub(delete?: true)
59
+
60
+ expect(responder).to receive(:display).with({}, status: :no_content)
61
+
62
+ responder.to_format
63
+ end
64
+
65
+ it 'falls through to super with errors' do
66
+ responder.stub(has_errors?: true)
67
+
68
+ expect(responder.to_format).to eq('{}')
69
+ end
70
+ end
@@ -0,0 +1,19 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+
4
+ require 'active_support'
5
+ require 'action_controller'
6
+ require 'rails/railtie'
7
+ require 'i18n'
8
+
9
+ ENV['RAILS_ENV'] = 'test'
10
+
11
+ require 'desponders'
12
+
13
+ RSpec.configure do |config|
14
+ config.treat_symbols_as_metadata_keys_with_true_values = true
15
+ config.run_all_when_everything_filtered = true
16
+ config.filter_run :focus
17
+
18
+ config.order = 'random'
19
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: desponders
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Parker Selbert
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '3.2'
20
+ - - <
21
+ - !ruby/object:Gem::Version
22
+ version: '5'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '3.2'
30
+ - - <
31
+ - !ruby/object:Gem::Version
32
+ version: '5'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '1.3'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '1.3'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 2.14.0
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ version: 2.14.0
75
+ description: A stack of light-weight responders tailored to JSON APIs
76
+ email:
77
+ - parker@sorentwo.com
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - .gitignore
83
+ - .rspec
84
+ - .travis.yml
85
+ - CHANGELOG.md
86
+ - Gemfile
87
+ - LICENSE.txt
88
+ - README.md
89
+ - Rakefile
90
+ - desponders.gemspec
91
+ - lib/desponders.rb
92
+ - lib/desponders/error_responder.rb
93
+ - lib/desponders/http_cache_responder.rb
94
+ - lib/desponders/locales/en.yml
95
+ - lib/desponders/paginated_responder.rb
96
+ - lib/desponders/rest_responder.rb
97
+ - lib/desponders/version.rb
98
+ - spec/desponders/error_responder_spec.rb
99
+ - spec/desponders/http_cache_responder_spec.rb
100
+ - spec/desponders/paginated_responder_spec.rb
101
+ - spec/desponders/rest_responder_spec.rb
102
+ - spec/spec_helper.rb
103
+ homepage: https://github.com/dscout/desponders
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.0.0
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: A stack of light-weight responders tailored to JSON APIs
127
+ test_files:
128
+ - spec/desponders/error_responder_spec.rb
129
+ - spec/desponders/http_cache_responder_spec.rb
130
+ - spec/desponders/paginated_responder_spec.rb
131
+ - spec/desponders/rest_responder_spec.rb
132
+ - spec/spec_helper.rb