spigot 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +25 -32
- data/Rakefile +6 -0
- data/examples/active_record.rb +18 -15
- data/examples/model.rb +38 -7
- data/lib/spigot.rb +18 -6
- data/lib/spigot/configuration.rb +4 -5
- data/lib/spigot/map/base.rb +44 -0
- data/lib/spigot/map/definition.rb +69 -0
- data/lib/spigot/map/option.rb +27 -0
- data/lib/spigot/map/resource.rb +37 -0
- data/lib/spigot/map/service.rb +43 -0
- data/lib/spigot/patch.rb +1 -1
- data/lib/spigot/proxy.rb +3 -2
- data/lib/spigot/translator.rb +22 -71
- data/lib/spigot/version.rb +1 -1
- data/script/console.rb +26 -20
- data/spec/fixtures/data/active_user.rb +17 -0
- data/spec/fixtures/data/post.rb +15 -0
- data/spec/fixtures/data/user.rb +41 -0
- data/spec/fixtures/mappings/active_user_map.rb +58 -22
- data/spec/fixtures/mappings/post_map.rb +10 -10
- data/spec/fixtures/mappings/user_map.rb +73 -29
- data/spec/spec_helper.rb +3 -12
- data/spec/spigot/active_record_spec.rb +34 -26
- data/spec/spigot/base_spec.rb +32 -1
- data/spec/spigot/configuration_spec.rb +0 -27
- data/spec/spigot/map/base_spec.rb +70 -0
- data/spec/spigot/map/definition_spec.rb +45 -0
- data/spec/spigot/map/resource_spec.rb +57 -0
- data/spec/spigot/map/service_spec.rb +88 -0
- data/spec/spigot/translator_spec.rb +110 -113
- data/spigot.gemspec +3 -2
- metadata +43 -20
- data/examples/.DS_Store +0 -0
- data/lib/.DS_Store +0 -0
- data/lib/spigot/config/.DS_Store +0 -0
- data/spec/.DS_Store +0 -0
- data/spec/fixtures/.DS_Store +0 -0
- data/spec/fixtures/api_data.rb +0 -46
- data/spec/spigot/factory_spec.rb +0 -5
@@ -0,0 +1,43 @@
|
|
1
|
+
module Spigot
|
2
|
+
module Map
|
3
|
+
class Service
|
4
|
+
|
5
|
+
attr_reader :name
|
6
|
+
attr_accessor :resources
|
7
|
+
|
8
|
+
def initialize(name)
|
9
|
+
@name = name.to_s.underscore.to_sym
|
10
|
+
@resources = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.service(name, &block)
|
14
|
+
service = find(name) || Spigot::Map::Service.new(name)
|
15
|
+
service.instance_eval(&block) if block_given?
|
16
|
+
current_map.update(name, service)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.find(name)
|
20
|
+
current_map.service(name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def resource(name, &block)
|
24
|
+
resources << Spigot::Map::Resource.new(name, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset
|
28
|
+
@resources = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def [](name)
|
32
|
+
resources.detect{|r| r.instance_variable_get(:@name).to_sym == name.to_sym}
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def self.current_map
|
38
|
+
Spigot.config.map
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/spigot/patch.rb
CHANGED
data/lib/spigot/proxy.rb
CHANGED
@@ -14,6 +14,7 @@ module Spigot
|
|
14
14
|
# @param service [String] This is the service that dictates the proxy.
|
15
15
|
# @param resource [Object] This is the class implementing the proxy.
|
16
16
|
def initialize(service, resource)
|
17
|
+
raise MissingServiceError, "No service definition found for #{service}" if Spigot.config.map.service(service).nil?
|
17
18
|
@service = service
|
18
19
|
@resource = resource
|
19
20
|
end
|
@@ -27,13 +28,13 @@ module Spigot
|
|
27
28
|
## #map
|
28
29
|
# Return a hash of the data map the current translator is using
|
29
30
|
def map
|
30
|
-
translator.
|
31
|
+
translator.resource_map
|
31
32
|
end
|
32
33
|
|
33
34
|
## #options
|
34
35
|
# Return a hash of any service specific options for this translator. `Spigot.config` not included
|
35
36
|
def options
|
36
|
-
translator.
|
37
|
+
translator.options || {}
|
37
38
|
end
|
38
39
|
|
39
40
|
end
|
data/lib/spigot/translator.rb
CHANGED
@@ -12,9 +12,7 @@ module Spigot
|
|
12
12
|
# in the yaml file for that resource.
|
13
13
|
#
|
14
14
|
# Relevant Configuration:
|
15
|
-
# config.options_key => The key which the Translator uses to configure a
|
16
|
-
# config.path => The path which the Translator will look in to find the mappings.
|
17
|
-
# config.translations => A hash that overrides any mappings found in the `path` directory.
|
15
|
+
# config.options_key => The key which the Translator uses to configure a resource_map.
|
18
16
|
|
19
17
|
attr_reader :service, :resource
|
20
18
|
attr_accessor :data
|
@@ -35,20 +33,10 @@ module Spigot
|
|
35
33
|
@data = data || {}
|
36
34
|
end
|
37
35
|
|
38
|
-
## #format
|
36
|
+
## #format
|
39
37
|
# Formats the hash of data passed in to the format specified in the yaml file.
|
40
|
-
|
41
|
-
|
42
|
-
# @param custom_data [Hash] Optional data that you can prefer to use over the @data currently on the object.
|
43
|
-
def format(custom_map=nil, custom_data=nil)
|
44
|
-
map = Hashie::Mash.new(custom_map || mapping)
|
45
|
-
dataset = custom_data || data
|
46
|
-
|
47
|
-
if dataset.is_a?(Array)
|
48
|
-
dataset.map{|n| translate(map, n) }
|
49
|
-
elsif dataset.is_a?(Hash)
|
50
|
-
translate(map, dataset)
|
51
|
-
end
|
38
|
+
def format
|
39
|
+
@format ||= data.is_a?(Array) ? data.map{|el| parse(el) } : parse(data)
|
52
40
|
end
|
53
41
|
|
54
42
|
## #id
|
@@ -78,81 +66,44 @@ module Spigot
|
|
78
66
|
# Default: nil
|
79
67
|
# Array of attributes included in the database query, these are names of columns in your database.
|
80
68
|
def options
|
81
|
-
@options ||=
|
69
|
+
@options ||= resource_map.instance_variable_get(:@options)
|
82
70
|
end
|
83
71
|
|
84
72
|
def primary_key
|
85
|
-
options
|
73
|
+
options.primary_key || "#{service}_id"
|
86
74
|
end
|
87
75
|
|
88
76
|
def foreign_key
|
89
|
-
options
|
77
|
+
options.foreign_key || 'id'
|
90
78
|
end
|
91
79
|
|
92
80
|
def conditions
|
93
|
-
|
94
|
-
keys = mapping.select{|k, v| p_keys.include?(v.to_s) }
|
95
|
-
format(keys)
|
81
|
+
{primary_key => format[primary_key]}
|
96
82
|
end
|
97
83
|
|
98
|
-
## #
|
99
|
-
# Return
|
100
|
-
def
|
101
|
-
return @
|
102
|
-
|
103
|
-
|
104
|
-
@
|
84
|
+
## #resource_map
|
85
|
+
# Return the mapped resource object for the current service and resource
|
86
|
+
def resource_map
|
87
|
+
return @resource_map if defined?(@resource_map)
|
88
|
+
resource_key = resource.to_s.underscore
|
89
|
+
@resource_map = service_map[resource_key]
|
90
|
+
raise MissingResourceError, "There is no #{resource_key} resource_map for #{service}" if @resource_map.nil?
|
91
|
+
@resource_map
|
105
92
|
end
|
106
93
|
|
107
94
|
private
|
108
95
|
|
109
|
-
def
|
96
|
+
def parse(dataset)
|
110
97
|
formatted = {}
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
else
|
115
|
-
dataset.each_pair do |key, val|
|
116
|
-
next if key == Spigot.config.options_key
|
117
|
-
attribute = map[key]
|
118
|
-
next if attribute.nil?
|
119
|
-
|
120
|
-
result = attribute.is_a?(Hash) ? translate(attribute, val) : val
|
121
|
-
formatted.merge! mergeable_content(key, result, map)
|
122
|
-
end
|
98
|
+
resource_map.definitions.each do |rule|
|
99
|
+
result = rule.parse(dataset)
|
100
|
+
formatted.merge!(result)
|
123
101
|
end
|
124
|
-
|
125
102
|
formatted
|
126
103
|
end
|
127
104
|
|
128
|
-
def
|
129
|
-
|
130
|
-
{key.to_s => value}
|
131
|
-
elsif value.is_a?(Hash)
|
132
|
-
value
|
133
|
-
else
|
134
|
-
{map[key] => value}
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def condition_keys
|
139
|
-
options['conditions'].to_s.split(',').map(&:strip)
|
140
|
-
end
|
141
|
-
|
142
|
-
def resource_key
|
143
|
-
resource.to_s.underscore
|
144
|
-
end
|
145
|
-
|
146
|
-
def translations
|
147
|
-
@translations ||= Hashie::Mash.new(Spigot.config.translations || YAML.load(translation_file))
|
148
|
-
end
|
149
|
-
|
150
|
-
def translation_file
|
151
|
-
begin
|
152
|
-
@translation_file ||= File.read(File.join(Spigot.config.path, "#{service.to_s}.yml"))
|
153
|
-
rescue Errno::ENOENT => e
|
154
|
-
raise MissingServiceError, "There is no service map for #{service} defined"
|
155
|
-
end
|
105
|
+
def service_map
|
106
|
+
Spigot.config.map ? Spigot.config.map.service(service) : {}
|
156
107
|
end
|
157
108
|
|
158
109
|
end
|
data/lib/spigot/version.rb
CHANGED
data/script/console.rb
CHANGED
@@ -1,6 +1,32 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'spigot'
|
3
3
|
|
4
|
+
Spigot.define do
|
5
|
+
service :github do
|
6
|
+
resource :active_user do
|
7
|
+
id :github_id
|
8
|
+
full_name :name
|
9
|
+
login :username
|
10
|
+
contact do
|
11
|
+
address :address
|
12
|
+
telephone do
|
13
|
+
work :work_phone
|
14
|
+
home :home_phone
|
15
|
+
end
|
16
|
+
url :homepage do |value|
|
17
|
+
"https://github.com/#{value}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
resource :pull_request do
|
23
|
+
id :id
|
24
|
+
title :title
|
25
|
+
body :body
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
4
30
|
ActiveRecord::Base.logger = Spigot.logger
|
5
31
|
require File.join(Spigot.root, 'spec', 'support', 'active_record')
|
6
32
|
|
@@ -8,24 +34,4 @@ class ActiveUser < ActiveRecord::Base
|
|
8
34
|
include Spigot::Base
|
9
35
|
end
|
10
36
|
|
11
|
-
map = {'activeuser' => {
|
12
|
-
'name' => 'name',
|
13
|
-
'username' => 'login',
|
14
|
-
'spigot' => {
|
15
|
-
'primary_key' => 'username'
|
16
|
-
}
|
17
|
-
}}
|
18
|
-
|
19
|
-
conditions = {'activeuser' => {
|
20
|
-
'name' => 'name',
|
21
|
-
'login' => 'username',
|
22
|
-
'spigot' => {
|
23
|
-
'primary_key' => 'username'
|
24
|
-
}
|
25
|
-
}}
|
26
|
-
|
27
|
-
Spigot.configure do |config|
|
28
|
-
config.translations = conditions
|
29
|
-
end
|
30
|
-
|
31
37
|
user = ActiveUser.create(name: 'Matt', username: 'mttwrnr', token: 'abc123')
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Spigot
|
2
|
+
module Data
|
3
|
+
class ActiveUser
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def basic
|
7
|
+
{full_name: 'Dean Martin', login: 'classyasfuck', auth_token: '123abc'}
|
8
|
+
end
|
9
|
+
|
10
|
+
def alt
|
11
|
+
{full_name: 'Frank Sinatra', login: 'livetilidie', auth_token: '987zyx'}
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Spigot
|
2
|
+
module Data
|
3
|
+
class Post
|
4
|
+
class << self
|
5
|
+
def basic
|
6
|
+
{'title' => 'Brief Article', 'body' => 'lorem ipsum'}
|
7
|
+
end
|
8
|
+
|
9
|
+
def alt
|
10
|
+
{'title' => 'Regular Article', 'body' => 'dolor sit amet', 'author' => 'Dean Martin'}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Spigot
|
2
|
+
module Data
|
3
|
+
class User
|
4
|
+
class << self
|
5
|
+
def basic
|
6
|
+
{'id' => '123', 'full_name' => 'Dean Martin', 'login' => 'classyasfuck'}
|
7
|
+
end
|
8
|
+
|
9
|
+
def alt
|
10
|
+
{'full_name' => 'Frank Sinatra', 'login' => 'livetilidie', 'auth_token' => '456bcd'}
|
11
|
+
end
|
12
|
+
|
13
|
+
def full
|
14
|
+
basic.merge('auth_token' => '123abc')
|
15
|
+
end
|
16
|
+
|
17
|
+
def array
|
18
|
+
[full, alt]
|
19
|
+
end
|
20
|
+
|
21
|
+
def nested_array
|
22
|
+
{'account' => 'Rockafella', 'users' => array, 'count' => 2}
|
23
|
+
end
|
24
|
+
|
25
|
+
def nested
|
26
|
+
full.merge('login' => login_info)
|
27
|
+
end
|
28
|
+
|
29
|
+
def double_nested
|
30
|
+
full.merge('login' => {'contact' => login_info, 'last_seen_ip' => '127.0.0.1'})
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def login_info
|
36
|
+
{'email' => 'dino@amore.io', 'user_name' => 'classyasfuck'}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,42 +1,78 @@
|
|
1
1
|
module Spigot
|
2
2
|
module Mapping
|
3
|
-
|
4
3
|
class ActiveUser
|
5
4
|
|
6
|
-
def self.
|
7
|
-
|
5
|
+
def self.stub
|
6
|
+
template do
|
7
|
+
login :username
|
8
|
+
full_name :name
|
9
|
+
end
|
8
10
|
end
|
9
11
|
|
10
12
|
def self.with_options
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
template do
|
14
|
+
login :username
|
15
|
+
full_name :name
|
16
|
+
options do
|
17
|
+
primary_key :username
|
18
|
+
foreign_key :login
|
19
|
+
end
|
20
|
+
end
|
16
21
|
end
|
17
22
|
|
18
|
-
def self.
|
19
|
-
|
23
|
+
def self.non_unique_keys
|
24
|
+
template do
|
25
|
+
login :username
|
26
|
+
full_name :name
|
27
|
+
auth_token :token
|
28
|
+
options do
|
29
|
+
primary_key :token
|
30
|
+
foreign_key :auth_token
|
31
|
+
end
|
32
|
+
end
|
20
33
|
end
|
21
34
|
|
22
35
|
private
|
23
36
|
|
24
|
-
def self.
|
25
|
-
|
37
|
+
def self.template(&block)
|
38
|
+
Spigot.define do
|
39
|
+
service :github do
|
40
|
+
resource :active_user do
|
41
|
+
self.instance_eval(&block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
26
45
|
end
|
27
46
|
|
28
|
-
def self.
|
29
|
-
|
30
|
-
end
|
47
|
+
# def self.basic
|
48
|
+
# {'active_user' => base}
|
49
|
+
# end
|
31
50
|
|
32
|
-
def self.
|
33
|
-
|
34
|
-
end
|
51
|
+
# def self.non_unique_key
|
52
|
+
# {'active_user' => base.merge('auth_token' => 'token', 'spigot' => non_unique)}
|
53
|
+
# end
|
35
54
|
|
36
|
-
def self.
|
37
|
-
|
38
|
-
end
|
39
|
-
|
55
|
+
# def self.with_invalid_options
|
56
|
+
# {'active_user' => base.merge('spigot' => invalid_options)}
|
57
|
+
# end
|
58
|
+
|
59
|
+
# private
|
60
|
+
|
61
|
+
# def self.base
|
62
|
+
# {'full_name' => 'name', 'login' => 'username'}
|
63
|
+
# end
|
40
64
|
|
65
|
+
# def self.options
|
66
|
+
# {'primary_key' => 'username', 'foreign_key' => 'login'}
|
67
|
+
# end
|
68
|
+
|
69
|
+
# def self.non_unique
|
70
|
+
# {'primary_key' => 'token', 'foreign_key' => 'auth_token'}
|
71
|
+
# end
|
72
|
+
|
73
|
+
# def self.invalid_options
|
74
|
+
# {'primary_key' => 'nosuchcolumn', 'foreign_key' => 'nosuchkey'}
|
75
|
+
# end
|
76
|
+
end
|
41
77
|
end
|
42
78
|
end
|