brainstem-adaptor 0.0.3
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 +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
|
+
[](https://travis-ci.org/einzige/brainstem-adaptor)
|
3
|
+
[](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: []
|