brainstem-adaptor 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +4 -0
- data/Gemfile +3 -0
- data/README.md +98 -0
- data/Rakefile +6 -0
- data/brainstem-adaptor.gemspec +25 -0
- data/lib/brainstem-adaptor.rb +40 -0
- data/lib/brainstem_adaptor/association.rb +73 -0
- data/lib/brainstem_adaptor/invalid_response_error.rb +12 -0
- data/lib/brainstem_adaptor/record.rb +74 -0
- data/lib/brainstem_adaptor/response.rb +57 -0
- data/lib/brainstem_adaptor/specification.rb +27 -0
- data/spec/lib/brainstem_adaptor/association_spec.rb +243 -0
- data/spec/lib/brainstem_adaptor/invalid_response_error_spec.rb +13 -0
- data/spec/lib/brainstem_adaptor/record_spec.rb +139 -0
- data/spec/lib/brainstem_adaptor/response_spec.rb +197 -0
- data/spec/lib/brainstem_adaptor/specification_spec.rb +15 -0
- data/spec/lib/brainstem_adaptor_spec.rb +35 -0
- data/spec/spec_helper.rb +8 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6746d8612cec0a387c002ad99c0a75615ef2c00c
|
4
|
+
data.tar.gz: f9cc76d40aaa1bc0fc53461f6caa7e6e34bbfc68
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fa62456fbccacbaa9236b7174acef004b4fdf101a85048432498d802bcf54b4910df7a11306de996467b5e5458ca284dd6d059929b3dc8a5cfc4396158940753
|
7
|
+
data.tar.gz: 09887da73e019a9b9ab8bc9b7f2a10b270ca780dcf3aede4cca0be0f2951907106e995eeeb1acb23c1f86ba448505fbe0db72863ab419b1decea0e44b7e65534
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
## Ruby Brainstem Adaptor
|
2
|
+
[![Build Status](https://travis-ci.org/einzige/brainstem-adaptor.svg?branch=master)](https://travis-ci.org/einzige/brainstem-adaptor)
|
3
|
+
[![Dependency Status](https://gemnasium.com/einzige/brainstem-ruby.svg)](https://gemnasium.com/einzige/brainstem-ruby)
|
4
|
+
|
5
|
+
Brainstem Adaptor provides an easy to use interface for [Brainstem](https://github.com/mavenlink/brainstem) API.
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
BrainstemAdaptor.load_specification('my_api_service.yml')
|
9
|
+
response_data = MyApi.get('/users.json')
|
10
|
+
|
11
|
+
# response_data can be a JSON string or Hash
|
12
|
+
response = BrainstemAdaptor::Response.new(response_data)
|
13
|
+
|
14
|
+
response.count # returns total count as Integer
|
15
|
+
# ...
|
16
|
+
response.results # returns Array<BrainstemAdaptor::Record>
|
17
|
+
response.results[0]['friends'] # returns Array<BrainstemAdaptor::Record>
|
18
|
+
|
19
|
+
response.results[0]['friends'].last['name']
|
20
|
+
|
21
|
+
response.results[0]['name'] # returns String
|
22
|
+
response.results[0].id # returns String or Integer
|
23
|
+
response.results[0]['mom'] # returns BrainstemAdaptor::Record
|
24
|
+
|
25
|
+
response.results[0]['mom']['name']
|
26
|
+
# ...
|
27
|
+
response['users'] # returns plain Hash as is from response
|
28
|
+
response['count'] # same here, Integer
|
29
|
+
```
|
30
|
+
|
31
|
+
## Installation
|
32
|
+
|
33
|
+
Run:
|
34
|
+
```bash
|
35
|
+
gem install brainstem-adaptor
|
36
|
+
```
|
37
|
+
|
38
|
+
Or put in your Gemfile:
|
39
|
+
```ruby
|
40
|
+
gem 'brainstem-adaptor'
|
41
|
+
```
|
42
|
+
|
43
|
+
## Configuration
|
44
|
+
#### Create specification for your API.
|
45
|
+
The only missing thing in Brainstem responses is an __associations information__.
|
46
|
+
Having `customer_ids` field does not guarantee that customer ids are related to `customers` collection, those may also be ids of `users` collection.
|
47
|
+
Specification is the thing which describes missing information about responses you receive.
|
48
|
+
You can also put any additional information you need in your specification (see details below).
|
49
|
+
|
50
|
+
```yaml
|
51
|
+
---
|
52
|
+
# my_api_service.yml file
|
53
|
+
users:
|
54
|
+
associations:
|
55
|
+
friends:
|
56
|
+
foreign_key: friend_ids
|
57
|
+
collection: 'users'
|
58
|
+
mom:
|
59
|
+
foreign_key: mom_id
|
60
|
+
collection: 'users'
|
61
|
+
|
62
|
+
projects:
|
63
|
+
fields:
|
64
|
+
name:
|
65
|
+
type: string
|
66
|
+
required: true
|
67
|
+
employee_ids:
|
68
|
+
type: array
|
69
|
+
|
70
|
+
associations:
|
71
|
+
employees:
|
72
|
+
foreign_key: employee_ids
|
73
|
+
collection: users
|
74
|
+
```
|
75
|
+
|
76
|
+
### Multiple specifications
|
77
|
+
|
78
|
+
You may also have multiple APIs which have different specificaitons.
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
BrainstemAdaptor::Specification[:my_tracker_api] = { 'users' => {} } # ...
|
82
|
+
response_data = MyApi.get('/users.json')
|
83
|
+
|
84
|
+
response = BrainstemAdaptor::Response.new(response_data, BrainstemAdaptor::Specification[:my_tracker_api])
|
85
|
+
# ...
|
86
|
+
```
|
87
|
+
|
88
|
+
## Contributing
|
89
|
+
|
90
|
+
1. Fork
|
91
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
92
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
93
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
94
|
+
5. Create new Pull Request (`git pull-request`)
|
95
|
+
|
96
|
+
## License
|
97
|
+
|
98
|
+
Brainstem Adaptor was created by Mavenlink, Inc. and are available under the MIT License.
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{brainstem-adaptor}
|
5
|
+
s.version = "0.0.3"
|
6
|
+
|
7
|
+
s.date = %q{2014-03-10}
|
8
|
+
s.authors = ["Sergei Zinin (einzige)"]
|
9
|
+
s.email = %q{szinin@gmail.com}
|
10
|
+
s.homepage = %q{http://github.com/einzige/brainstem-adaptor}
|
11
|
+
|
12
|
+
s.licenses = ["MIT"]
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.extra_rdoc_files = ["README.md"]
|
17
|
+
|
18
|
+
s.description = %q{Parses Brainstem responses, makes it convenient to organize access to your data.}
|
19
|
+
s.summary = %q{Brainstem API Adaptor}
|
20
|
+
|
21
|
+
s.add_development_dependency 'rspec'
|
22
|
+
s.add_runtime_dependency 'activesupport', ">= 3.0.0"
|
23
|
+
end
|
24
|
+
|
25
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
4
|
+
require 'active_support/core_ext/hash/slice'
|
5
|
+
require 'active_support/core_ext/object/try'
|
6
|
+
require 'brainstem_adaptor/specification'
|
7
|
+
require 'brainstem_adaptor/association'
|
8
|
+
require 'brainstem_adaptor/record'
|
9
|
+
require 'brainstem_adaptor/invalid_response_error'
|
10
|
+
require 'brainstem_adaptor/response'
|
11
|
+
|
12
|
+
module BrainstemAdaptor
|
13
|
+
VERSION = '0.0.3'
|
14
|
+
|
15
|
+
def self.parser
|
16
|
+
@parser ||= JSON
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param parser Any JSON parser
|
20
|
+
# @raise [ArgumentError] if parser does not respond to #parse
|
21
|
+
def self.parser=(parser)
|
22
|
+
raise ArgumentError, 'Parser must respond to #parse message' unless parser.respond_to?(:parse)
|
23
|
+
@parser = parser
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [BrainstemAdaptor::Specification]
|
27
|
+
def self.default_specification
|
28
|
+
BrainstemAdaptor::Specification[:default]
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param specification [Hash]
|
32
|
+
def self.specification=(specification)
|
33
|
+
BrainstemAdaptor::Specification[:default] = specification
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param path [String] Path to YML specification file
|
37
|
+
def self.load_specification(path)
|
38
|
+
self.specification = YAML::load_file(path)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module BrainstemAdaptor
|
2
|
+
class Association
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :name, :record, :specification, :collection_name, :foreign_key
|
6
|
+
|
7
|
+
# @param record [BrainstemAdaptor::Record]
|
8
|
+
# @param name [String, Symbol]
|
9
|
+
def initialize(record, name)
|
10
|
+
@name = name.to_s
|
11
|
+
|
12
|
+
unless record.has_association?(@name)
|
13
|
+
raise ArgumentError, "No '#@name' specification found for #{record.collection_name}"
|
14
|
+
end
|
15
|
+
|
16
|
+
@record = record
|
17
|
+
@specification = record.associations_specification[@name]
|
18
|
+
@collection_name = @specification['collection'] || @name
|
19
|
+
@foreign_key = @specification['foreign_key']
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param other [Enumerable]
|
23
|
+
# @return [true, false]
|
24
|
+
def ==(other)
|
25
|
+
other == each.to_a
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param order [Integer] Index in collection starting from zero
|
29
|
+
def [](order)
|
30
|
+
records[order]
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Enumerable]
|
34
|
+
def each(&block)
|
35
|
+
records.each(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def has_many?
|
39
|
+
ids.is_a?(Array)
|
40
|
+
end
|
41
|
+
|
42
|
+
def has_one?
|
43
|
+
!has_many?
|
44
|
+
end
|
45
|
+
|
46
|
+
# Checks if association has been included in request
|
47
|
+
# @return [true, false]
|
48
|
+
def loaded?
|
49
|
+
(!record[foreign_key].nil?) && (!!record.response[@collection_name].try(:any?))
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Array<BrainstemAdaptor::Record>]
|
53
|
+
def records
|
54
|
+
[*ids].map do |id|
|
55
|
+
BrainstemAdaptor::Record.new(collection_name, id, record.response)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
alias_method :all, :records
|
59
|
+
|
60
|
+
# Returns relation object for has_many associations and record for has_one
|
61
|
+
# Acts as AR::find for has_one associations, as AR::where for has_many
|
62
|
+
# @return [BrainstemAdaptor::Record, self]
|
63
|
+
def reflect
|
64
|
+
has_many? ? self : records.first
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def ids # TODO(SZ): move to public?
|
70
|
+
record[foreign_key]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module BrainstemAdaptor
|
2
|
+
class InvalidResponseError < StandardError
|
3
|
+
attr_reader :response
|
4
|
+
|
5
|
+
# @param [Hash] response
|
6
|
+
# @param [Stirng] message
|
7
|
+
def initialize(response, message = response.inspect)
|
8
|
+
@response = response
|
9
|
+
super(message)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module BrainstemAdaptor
|
2
|
+
class Record < ActiveSupport::HashWithIndifferentAccess
|
3
|
+
attr_reader :collection_name, :id, :response
|
4
|
+
|
5
|
+
# @param collection_name [String, Symbol]
|
6
|
+
# @param id
|
7
|
+
# @param response [BrainstemAdaptor::Response, nil]
|
8
|
+
def initialize(collection_name, id, response = nil)
|
9
|
+
super([])
|
10
|
+
@collection_name = collection_name.to_s
|
11
|
+
@id = id
|
12
|
+
load_fields_with(response) if response
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param key [String]
|
16
|
+
def [](key)
|
17
|
+
if has_key?(key = key.to_s)
|
18
|
+
super
|
19
|
+
elsif has_association?(key)
|
20
|
+
association_by_name(key).reflect
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Hash]
|
25
|
+
def associations_specification
|
26
|
+
@associations_specification ||= specification['associations'] || {}
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param name [String]
|
30
|
+
# @raise [ArgumentError] if name is not related to any association
|
31
|
+
# @return [BrainstemAdaptor::Association]
|
32
|
+
def association_by_name(name)
|
33
|
+
if has_association?(name)
|
34
|
+
(@associations ||= {})[name] ||= BrainstemAdaptor::Association.new(self, name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param name [String]
|
39
|
+
def has_association?(name)
|
40
|
+
associations_specification.has_key?(name.to_s)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Hash]
|
44
|
+
def specification
|
45
|
+
@specification ||= {}
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
# @param response [Brainstem::Response]
|
51
|
+
# @param fields_to_reload [Array] Reloads all fields if empty
|
52
|
+
def load_fields_with(response, fields_to_reload = [])
|
53
|
+
@response = response
|
54
|
+
|
55
|
+
if @response.specification.has_key?(collection_name)
|
56
|
+
@specification = @response.specification[collection_name] || {}
|
57
|
+
else
|
58
|
+
raise BrainstemAdaptor::InvalidResponseError, "Can't find '#{collection_name}' association in specification"
|
59
|
+
end
|
60
|
+
|
61
|
+
collection = @response[@collection_name] or
|
62
|
+
raise BrainstemAdaptor::InvalidResponseError, "No such collection #@collection_name"
|
63
|
+
|
64
|
+
fields = collection[@id] or
|
65
|
+
raise BrainstemAdaptor::InvalidResponseError, "No such record #{@collection_name}##{@id}"
|
66
|
+
|
67
|
+
if fields_to_reload.any?
|
68
|
+
merge!(fields.slice(*fields_to_reload))
|
69
|
+
else
|
70
|
+
merge!(fields)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module BrainstemAdaptor
|
2
|
+
class Response
|
3
|
+
attr_reader :response_data, :specification
|
4
|
+
|
5
|
+
# @param response_data [String, Hash]
|
6
|
+
# @param specification [BrainstemAdaptor::Specification]
|
7
|
+
def initialize(response_data, specification = BrainstemAdaptor.default_specification)
|
8
|
+
@specification = specification or raise ArgumentError, 'Specification is not set'
|
9
|
+
|
10
|
+
case response_data
|
11
|
+
when String
|
12
|
+
@response_data = BrainstemAdaptor.parser.parse(response_data)
|
13
|
+
when Hash
|
14
|
+
@response_data = response_data
|
15
|
+
else
|
16
|
+
raise ArgumentError, "Expected String, got #{@response_data.class.name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
raise InvalidResponseError, "count isn't returned" unless @response_data['count']
|
20
|
+
raise InvalidResponseError, "results collection isn't returned" unless @response_data['results']
|
21
|
+
raise InvalidResponseError, "results collection is not an array" unless @response_data['results'].is_a?(Array)
|
22
|
+
|
23
|
+
rescue JSON::ParserError => e
|
24
|
+
raise BrainstemAdaptor::InvalidResponseError, response_data, e.message
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param key [String, Symbol]
|
28
|
+
# @return [Hash, nil]
|
29
|
+
def [](key)
|
30
|
+
response_data[key.to_s]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns __TOTAL__ number of records
|
34
|
+
# @return [Integer]
|
35
|
+
def count
|
36
|
+
response_data['count']
|
37
|
+
end
|
38
|
+
alias_method :total_count, :count
|
39
|
+
|
40
|
+
# @return [String]
|
41
|
+
def to_hash
|
42
|
+
response_data
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns results has with proper ordering
|
46
|
+
# @return [Array<BrainstemAdaptor::Record>]
|
47
|
+
def results
|
48
|
+
self['results'].map do |result|
|
49
|
+
BrainstemAdaptor::Record.new(result['key'], result['id'], self)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def ==(other)
|
54
|
+
other == response_data
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module BrainstemAdaptor
|
2
|
+
class Specification < Hash
|
3
|
+
|
4
|
+
# @param specification [Hash]
|
5
|
+
def initialize(specification)
|
6
|
+
super
|
7
|
+
self.merge!(specification)
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [Hash]
|
11
|
+
def self.instances
|
12
|
+
@instances ||= {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param key [Symbol] Specification name
|
16
|
+
# @return [BrainstemAdaptor::Specification]
|
17
|
+
def self.[](key)
|
18
|
+
self.instances[key.to_sym] or raise ArgumentError, "No such specification '#{key}'"
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param key [Symbol] Specification name
|
22
|
+
# @param value [Hash] Specification body
|
23
|
+
def self.[]=(key, value)
|
24
|
+
self.instances[key.to_sym] = self.new(value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BrainstemAdaptor::Association do
|
4
|
+
let(:nickolai) { { 'name' => 'Nickolai', 'friend_ids' => ['13', '14'], 'enemy_id' => '14' } }
|
5
|
+
let(:ivan) { { 'name' => 'Ivan', 'friend_ids' => [], 'enemy_id' => '12' } }
|
6
|
+
let(:anatolii) { { 'name' => 'Anatolii', 'friend_ids' => ['13', '14'], 'enemy_id' => '12' } }
|
7
|
+
|
8
|
+
let(:response_data) do
|
9
|
+
{
|
10
|
+
'count' => 0,
|
11
|
+
'results' => [],
|
12
|
+
'users' => {
|
13
|
+
'12' => nickolai,
|
14
|
+
'13' => ivan,
|
15
|
+
'14' => anatolii
|
16
|
+
}
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:specification) do
|
21
|
+
{
|
22
|
+
'users' => {
|
23
|
+
'fields' => {
|
24
|
+
'name' => {}
|
25
|
+
},
|
26
|
+
'associations' => {
|
27
|
+
'friends' => {
|
28
|
+
'foreign_key' => 'friend_ids',
|
29
|
+
'collection' => 'users'
|
30
|
+
},
|
31
|
+
'enemy' => {
|
32
|
+
'foreign_key' => 'enemy_id',
|
33
|
+
'collection' => 'users'
|
34
|
+
},
|
35
|
+
'mother_in_law' => {
|
36
|
+
'foreign_key' => 'mother_in_law_id',
|
37
|
+
'collection' => 'users'
|
38
|
+
},
|
39
|
+
'some_empty' => {
|
40
|
+
'foreign_key' => 'friend_ids',
|
41
|
+
'collection' => 'some_empty_collection'
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
let(:response) do
|
49
|
+
BrainstemAdaptor::Response.new(response_data, specification)
|
50
|
+
end
|
51
|
+
|
52
|
+
let(:nickolai_user) { BrainstemAdaptor::Record.new('users', '12', response) }
|
53
|
+
let(:ivan_user) { BrainstemAdaptor::Record.new('users', '13', response) }
|
54
|
+
let(:anatolii_user) { BrainstemAdaptor::Record.new('users', '14', response) }
|
55
|
+
|
56
|
+
let(:nickolai_friends) { described_class.new(nickolai_user, 'friends') }
|
57
|
+
let(:ivan_friends) { described_class.new(ivan_user, 'friends') }
|
58
|
+
let(:anatoliy_friends) { described_class.new(anatolii_user, 'friends') }
|
59
|
+
|
60
|
+
let(:nickolai_enemy) { described_class.new(nickolai_user, 'enemy') }
|
61
|
+
let(:ivan_enemy) { described_class.new(ivan_user, 'enemy') }
|
62
|
+
let(:anatoliy_enemy) { described_class.new(anatolii_user, 'enemy') }
|
63
|
+
|
64
|
+
describe '#==' do
|
65
|
+
context 'has_many relations' do
|
66
|
+
specify do
|
67
|
+
expect(nickolai_friends).to eq(anatoliy_friends)
|
68
|
+
end
|
69
|
+
|
70
|
+
specify do
|
71
|
+
expect(nickolai_friends).not_to eq(ivan_friends)
|
72
|
+
end
|
73
|
+
|
74
|
+
specify do
|
75
|
+
expect(nickolai_friends).to eq(nickolai_friends)
|
76
|
+
end
|
77
|
+
|
78
|
+
specify do
|
79
|
+
expect(ivan_friends).not_to eq(nickolai_friends)
|
80
|
+
end
|
81
|
+
|
82
|
+
specify do
|
83
|
+
expect(ivan_friends).not_to eq(anatoliy_friends)
|
84
|
+
end
|
85
|
+
|
86
|
+
specify do
|
87
|
+
expect(ivan_friends).to eq(ivan_friends)
|
88
|
+
end
|
89
|
+
|
90
|
+
specify do
|
91
|
+
expect(anatoliy_friends).to eq(nickolai_friends)
|
92
|
+
end
|
93
|
+
|
94
|
+
specify do
|
95
|
+
expect(anatoliy_friends).not_to eq(ivan_friends)
|
96
|
+
end
|
97
|
+
|
98
|
+
specify do
|
99
|
+
expect(anatoliy_friends).to eq(anatoliy_friends)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'has_one relations' do
|
104
|
+
specify do
|
105
|
+
expect(nickolai_enemy).not_to eq(anatoliy_enemy)
|
106
|
+
end
|
107
|
+
|
108
|
+
specify do
|
109
|
+
expect(nickolai_enemy).not_to eq(ivan_enemy)
|
110
|
+
end
|
111
|
+
|
112
|
+
specify do
|
113
|
+
expect(nickolai_enemy).to eq(nickolai_enemy)
|
114
|
+
end
|
115
|
+
|
116
|
+
specify do
|
117
|
+
expect(ivan_enemy).not_to eq(nickolai_enemy)
|
118
|
+
end
|
119
|
+
|
120
|
+
specify do
|
121
|
+
expect(ivan_enemy).to eq(anatoliy_enemy)
|
122
|
+
end
|
123
|
+
|
124
|
+
specify do
|
125
|
+
expect(ivan_enemy).to eq(ivan_enemy)
|
126
|
+
end
|
127
|
+
|
128
|
+
specify do
|
129
|
+
expect(anatoliy_enemy).not_to eq(nickolai_enemy)
|
130
|
+
end
|
131
|
+
|
132
|
+
specify do
|
133
|
+
expect(anatoliy_enemy).to eq(ivan_enemy)
|
134
|
+
end
|
135
|
+
|
136
|
+
specify do
|
137
|
+
expect(anatoliy_enemy).to eq(anatoliy_enemy)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#[]' do
|
143
|
+
specify do
|
144
|
+
expect(nickolai_friends[0]).to eq(ivan)
|
145
|
+
end
|
146
|
+
|
147
|
+
specify do
|
148
|
+
expect(nickolai_friends[0]).to eq(ivan_user)
|
149
|
+
end
|
150
|
+
|
151
|
+
specify do
|
152
|
+
expect(nickolai_friends[1]).to eq(anatolii)
|
153
|
+
end
|
154
|
+
|
155
|
+
specify do
|
156
|
+
expect(nickolai_friends[1]).to eq(anatolii_user)
|
157
|
+
end
|
158
|
+
|
159
|
+
specify do
|
160
|
+
expect(nickolai_friends[2]).to be_nil
|
161
|
+
end
|
162
|
+
|
163
|
+
specify do
|
164
|
+
expect(nickolai_enemy[0]).to eq(anatolii)
|
165
|
+
end
|
166
|
+
|
167
|
+
specify do
|
168
|
+
expect(nickolai_enemy[0]).to eq(anatolii_user)
|
169
|
+
end
|
170
|
+
|
171
|
+
specify do
|
172
|
+
expect(nickolai_enemy[1]).to be_nil
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe '#each' do
|
177
|
+
specify do
|
178
|
+
expect(nickolai_friends.each).to be_a Enumerable
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe '#records' do
|
183
|
+
specify do
|
184
|
+
expect(nickolai_friends.records).to eq([ivan, anatolii])
|
185
|
+
end
|
186
|
+
|
187
|
+
specify do
|
188
|
+
expect(nickolai_enemy.records).to eq([anatolii])
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe '#reflect' do
|
193
|
+
specify do
|
194
|
+
expect(nickolai_friends.reflect).to eq(nickolai_friends)
|
195
|
+
end
|
196
|
+
|
197
|
+
specify do
|
198
|
+
expect(nickolai_enemy.reflect).to eq(anatolii)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context 'association is not included in specification' do
|
203
|
+
subject { described_class.new(nickolai_user, 'something wrong') }
|
204
|
+
|
205
|
+
specify do
|
206
|
+
expect { subject }.to raise_error ArgumentError, /specification/
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe '#has_many?' do
|
211
|
+
specify do
|
212
|
+
expect(nickolai_friends.has_many?).to eq(true)
|
213
|
+
end
|
214
|
+
|
215
|
+
specify do
|
216
|
+
expect(nickolai_enemy.has_many?).to eq(false)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe '#has_one?' do
|
221
|
+
specify do
|
222
|
+
expect(nickolai_friends.has_one?).to eq(false)
|
223
|
+
end
|
224
|
+
|
225
|
+
specify do
|
226
|
+
expect(nickolai_enemy.has_one?).to eq(true)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe '#loaded?' do
|
231
|
+
specify do
|
232
|
+
expect(nickolai_user.association_by_name('mother_in_law').loaded?).to eq(false)
|
233
|
+
end
|
234
|
+
|
235
|
+
specify do
|
236
|
+
expect(nickolai_user.association_by_name('friends').loaded?).to eq(true)
|
237
|
+
end
|
238
|
+
|
239
|
+
specify do
|
240
|
+
expect(nickolai_user.association_by_name('some_empty').loaded?).to eq(false)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BrainstemAdaptor::InvalidResponseError do
|
4
|
+
subject { described_class.new(response) }
|
5
|
+
let(:response) { {failed: true} }
|
6
|
+
|
7
|
+
its(:response) { should == response }
|
8
|
+
its(:message) { should include('failed') }
|
9
|
+
|
10
|
+
specify do
|
11
|
+
expect { raise BrainstemAdaptor::InvalidResponseError, 'failed' }.to raise_error(described_class)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BrainstemAdaptor::Record do
|
4
|
+
let(:response_data) do
|
5
|
+
{
|
6
|
+
'count' => 0,
|
7
|
+
'results' => [],
|
8
|
+
'users' => {
|
9
|
+
'12' => { 'name' => 'Petr', 'friend_ids' => ['13'], 'enemy_id' => nil },
|
10
|
+
'13' => { 'name' => 'Pelat', 'friend_ids' => [], 'enemy_id' => '12' },
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:specification) do
|
16
|
+
{
|
17
|
+
'users' => {
|
18
|
+
'fields' => {
|
19
|
+
'name' => {}
|
20
|
+
},
|
21
|
+
'associations' => {
|
22
|
+
'friends' => {
|
23
|
+
'foreign_key' => 'friend_ids',
|
24
|
+
'collection' => 'users'
|
25
|
+
},
|
26
|
+
'enemy' => {
|
27
|
+
'foreign_key' => 'enemy_id',
|
28
|
+
'collection' => 'users'
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:response) do
|
36
|
+
BrainstemAdaptor::Response.new(response_data, specification)
|
37
|
+
end
|
38
|
+
|
39
|
+
subject { described_class.new('users', '12', response) }
|
40
|
+
|
41
|
+
its(:id) { should == '12' }
|
42
|
+
its(:collection_name) { should == 'users' }
|
43
|
+
its(:response) { should == response }
|
44
|
+
its(:associations_specification) { should == specification['users']['associations'] }
|
45
|
+
|
46
|
+
context 'invalid response' do
|
47
|
+
context 'collection is not described in specification' do
|
48
|
+
let(:specification) { {} }
|
49
|
+
|
50
|
+
specify do
|
51
|
+
expect { subject }.to raise_error BrainstemAdaptor::InvalidResponseError, /association/
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'collection is not included in response' do
|
56
|
+
let(:response_data) { {'count' => 0, 'results' => []} }
|
57
|
+
|
58
|
+
specify do
|
59
|
+
expect { subject }.to raise_error BrainstemAdaptor::InvalidResponseError, /collection/
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'record is not listed in collection' do
|
64
|
+
let(:response_data) { {'count' => 0, 'results' => [], 'users' => {} } }
|
65
|
+
|
66
|
+
specify do
|
67
|
+
expect { subject }.to raise_error BrainstemAdaptor::InvalidResponseError, /record/
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#[]' do
|
73
|
+
specify do
|
74
|
+
expect(subject['name']).to eq('Petr')
|
75
|
+
end
|
76
|
+
|
77
|
+
specify do
|
78
|
+
expect(subject['friends']).to eq([{'name' => 'Pelat', 'friend_ids' => [], 'enemy_id' => '12'}])
|
79
|
+
end
|
80
|
+
|
81
|
+
specify do
|
82
|
+
expect(subject['enemy']).to be_nil
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'inverse' do
|
86
|
+
subject { described_class.new('users', '13', response) }
|
87
|
+
|
88
|
+
specify do
|
89
|
+
expect(subject['name']).to eq('Pelat')
|
90
|
+
end
|
91
|
+
|
92
|
+
specify do
|
93
|
+
expect(subject['friends']).to be_a Enumerable
|
94
|
+
end
|
95
|
+
|
96
|
+
specify do
|
97
|
+
expect(subject['friends'].any?).to eq(false)
|
98
|
+
end
|
99
|
+
|
100
|
+
specify do
|
101
|
+
expect(subject['enemy']).to be_a BrainstemAdaptor::Record
|
102
|
+
end
|
103
|
+
|
104
|
+
specify do
|
105
|
+
expect(subject['enemy']).to eq({'name' => 'Petr', 'friend_ids' => ['13'], 'enemy_id' => nil})
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#has_association?' do
|
111
|
+
specify do
|
112
|
+
expect(subject.has_association?('friends')).to eq(true)
|
113
|
+
end
|
114
|
+
|
115
|
+
specify do
|
116
|
+
expect(subject.has_association?('something invalid')).to eq(false)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '#association_by_name' do
|
121
|
+
context 'association exists' do
|
122
|
+
specify do
|
123
|
+
expect(subject.association_by_name('friends')).to be_a BrainstemAdaptor::Association
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'association does not exist' do
|
128
|
+
specify do
|
129
|
+
expect(subject.association_by_name('something wrong')).to be_nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'no specification set' do
|
135
|
+
specify do
|
136
|
+
expect { described_class.new('test', 1)['any key'] }.not_to raise_error
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BrainstemAdaptor::Response do
|
4
|
+
let(:plain_text_response) do
|
5
|
+
<<-JSON_RESPONSE
|
6
|
+
{
|
7
|
+
"count": 99,
|
8
|
+
"results": [{ "key": "workspaces", "id": "10" }, { "key": "workspaces", "id": "11" }],
|
9
|
+
"workspaces": {
|
10
|
+
"10": {
|
11
|
+
"id": "10",
|
12
|
+
"title": "some project",
|
13
|
+
"participant_ids": ["2", "6"],
|
14
|
+
"primary_counterpart_id": "6"
|
15
|
+
},
|
16
|
+
"11": {
|
17
|
+
"id": "11",
|
18
|
+
"title": "another project",
|
19
|
+
"participant_ids": ["2", "8"],
|
20
|
+
"primary_counterpart_id": "8"
|
21
|
+
}
|
22
|
+
},
|
23
|
+
"users": {
|
24
|
+
"2": { "id": "2", "full_name": "bob" },
|
25
|
+
"6": { "id": "6", "full_name": "chaz" },
|
26
|
+
"8": { "id": "8", "full_name": "jane" }
|
27
|
+
}
|
28
|
+
}
|
29
|
+
JSON_RESPONSE
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:response_hash) { BrainstemAdaptor.parser.parse(plain_text_response) }
|
33
|
+
|
34
|
+
let(:specification) do
|
35
|
+
{
|
36
|
+
'workspaces' => {
|
37
|
+
'associations' => {
|
38
|
+
'participants' => {
|
39
|
+
'foreign_key' => 'participant_ids',
|
40
|
+
'collection' => 'users'
|
41
|
+
},
|
42
|
+
'primary_counterpart' => {
|
43
|
+
'foreign_key' => 'primary_counterpart_id',
|
44
|
+
'collection' => 'users'
|
45
|
+
}
|
46
|
+
}
|
47
|
+
},
|
48
|
+
'users' => nil
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
before do
|
53
|
+
BrainstemAdaptor.specification = specification
|
54
|
+
end
|
55
|
+
|
56
|
+
let(:response_data) { plain_text_response }
|
57
|
+
|
58
|
+
subject(:response) { described_class.new(response_data) }
|
59
|
+
|
60
|
+
describe 'collection' do
|
61
|
+
its(:count) { should == 99 }
|
62
|
+
|
63
|
+
specify do
|
64
|
+
expect(response.results).to have(2).records
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'records data' do
|
68
|
+
specify do
|
69
|
+
expect(response.results[0]).to be_a BrainstemAdaptor::Record
|
70
|
+
end
|
71
|
+
|
72
|
+
specify do
|
73
|
+
expect(response.results[1]).to be_a BrainstemAdaptor::Record
|
74
|
+
end
|
75
|
+
|
76
|
+
specify do
|
77
|
+
expect(response.results[0].collection_name).to eq('workspaces')
|
78
|
+
end
|
79
|
+
|
80
|
+
specify do
|
81
|
+
expect(response.results[1].collection_name).to eq('workspaces')
|
82
|
+
end
|
83
|
+
|
84
|
+
specify do
|
85
|
+
expect(response.results[0]).to eq(response_hash['workspaces']['10'])
|
86
|
+
end
|
87
|
+
|
88
|
+
specify do
|
89
|
+
expect(response.results[1]).to eq(response_hash['workspaces']['11'])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'associations' do
|
95
|
+
specify do
|
96
|
+
expect(response['users']).to eq(response_hash['users'])
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '"has many" relations' do
|
100
|
+
specify do
|
101
|
+
expect(response.results[0]['participants'][0]).to be_a BrainstemAdaptor::Record
|
102
|
+
end
|
103
|
+
|
104
|
+
specify do
|
105
|
+
expect(response.results[0]['participants'][1]).to be_a BrainstemAdaptor::Record
|
106
|
+
end
|
107
|
+
|
108
|
+
specify do
|
109
|
+
expect(response.results[1]['participants'][0]).to be_a BrainstemAdaptor::Record
|
110
|
+
end
|
111
|
+
|
112
|
+
specify do
|
113
|
+
expect(response.results[1]['participants'][1]).to be_a BrainstemAdaptor::Record
|
114
|
+
end
|
115
|
+
|
116
|
+
specify do
|
117
|
+
expect(response.results[0]['participants']).to eq([response_hash['users']['2'], response_hash['users']['6']])
|
118
|
+
end
|
119
|
+
|
120
|
+
specify do
|
121
|
+
expect(response.results[1]['participants']).to eq([response_hash['users']['2'], response_hash['users']['8']])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '"has one" relations' do
|
126
|
+
specify do
|
127
|
+
expect(response.results[0]['primary_counterpart']).to be_a BrainstemAdaptor::Record
|
128
|
+
end
|
129
|
+
|
130
|
+
specify do
|
131
|
+
expect(response.results[1]['primary_counterpart']).to be_a BrainstemAdaptor::Record
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'invalid JSON format' do
|
137
|
+
let(:response_data) { 'test; invalid " json ' }
|
138
|
+
|
139
|
+
specify do
|
140
|
+
expect { subject }.to raise_error BrainstemAdaptor::InvalidResponseError
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'parsed input' do
|
145
|
+
let(:response_data) { response_hash }
|
146
|
+
|
147
|
+
specify do
|
148
|
+
expect(subject.response_data).to eq(response_data)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'invalid input' do
|
153
|
+
let(:response_data) { nil }
|
154
|
+
|
155
|
+
specify do
|
156
|
+
expect { subject }.to raise_error ArgumentError, /Expected String/
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'count is not returned' do
|
160
|
+
let(:response_data) { { 'results' => [] } }
|
161
|
+
|
162
|
+
specify do
|
163
|
+
expect { subject }.to raise_error BrainstemAdaptor::InvalidResponseError, /count/
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'results collection is not returned' do
|
168
|
+
let(:response_data) { { 'count' => 0 } }
|
169
|
+
|
170
|
+
specify do
|
171
|
+
expect { subject }.to raise_error BrainstemAdaptor::InvalidResponseError, /results.*returned/
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'results collection is not an array' do
|
176
|
+
let(:response_data) { { 'count' => 0, 'results' => {} } }
|
177
|
+
|
178
|
+
specify do
|
179
|
+
expect { subject }.to raise_error BrainstemAdaptor::InvalidResponseError, /results.*array/
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe '#to_hash' do
|
185
|
+
specify do
|
186
|
+
expect(subject.to_hash).to eq(response_hash)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe '#==' do
|
191
|
+
let(:response_data) { { 'count' => 1, 'results' => [{'key' => 'user', 'value' => 2}] } }
|
192
|
+
|
193
|
+
specify do
|
194
|
+
expect(subject).to eq(response_data)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BrainstemAdaptor::Specification do
|
4
|
+
describe '.[]' do
|
5
|
+
before do
|
6
|
+
described_class[:test] = {stored: true}
|
7
|
+
described_class[:another_test] = {something_else: false}
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'stores multiple specifications' do
|
11
|
+
expect(described_class[:test]).to eq({stored: true})
|
12
|
+
expect(described_class[:another_test]).to eq({something_else: false})
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BrainstemAdaptor do
|
4
|
+
describe '.parser=' do
|
5
|
+
let(:parser) { double('real parser', parse: true) }
|
6
|
+
|
7
|
+
specify do
|
8
|
+
expect { described_class.parser = parser }.to change(described_class, :parser).to(parser)
|
9
|
+
end
|
10
|
+
|
11
|
+
specify do
|
12
|
+
expect { described_class.parser = double('something wrong') }.to raise_error ArgumentError
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.parser' do
|
17
|
+
it 'users JSON parser by default' do
|
18
|
+
expect { described_class.parser }.not_to raise_error
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.default_specification' do
|
23
|
+
specify do
|
24
|
+
expect { described_class.default_specification }.not_to raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '.specification=' do
|
29
|
+
let(:specification) { {users: {}} }
|
30
|
+
|
31
|
+
specify do
|
32
|
+
expect { described_class.specification = specification }.to change(described_class, :default_specification).to(specification)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: brainstem-adaptor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergei Zinin (einzige)
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.0
|
41
|
+
description: Parses Brainstem responses, makes it convenient to organize access to
|
42
|
+
your data.
|
43
|
+
email: szinin@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files:
|
47
|
+
- README.md
|
48
|
+
files:
|
49
|
+
- .gitignore
|
50
|
+
- .travis.yml
|
51
|
+
- Gemfile
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- brainstem-adaptor.gemspec
|
55
|
+
- lib/brainstem-adaptor.rb
|
56
|
+
- lib/brainstem_adaptor/association.rb
|
57
|
+
- lib/brainstem_adaptor/invalid_response_error.rb
|
58
|
+
- lib/brainstem_adaptor/record.rb
|
59
|
+
- lib/brainstem_adaptor/response.rb
|
60
|
+
- lib/brainstem_adaptor/specification.rb
|
61
|
+
- spec/lib/brainstem_adaptor/association_spec.rb
|
62
|
+
- spec/lib/brainstem_adaptor/invalid_response_error_spec.rb
|
63
|
+
- spec/lib/brainstem_adaptor/record_spec.rb
|
64
|
+
- spec/lib/brainstem_adaptor/response_spec.rb
|
65
|
+
- spec/lib/brainstem_adaptor/specification_spec.rb
|
66
|
+
- spec/lib/brainstem_adaptor_spec.rb
|
67
|
+
- spec/spec_helper.rb
|
68
|
+
homepage: http://github.com/einzige/brainstem-adaptor
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.1.5
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Brainstem API Adaptor
|
92
|
+
test_files: []
|