api-query-provider 0.0.1
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.
- data/.document +5 -0
- data/.travis.yml +3 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +43 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +10 -0
- data/Rakefile +49 -0
- data/TODO +8 -0
- data/VERSION +1 -0
- data/api-query-provider.gemspec +85 -0
- data/lib/api-query-provider.rb +6 -0
- data/lib/api-query-provider/base.rb +152 -0
- data/lib/api-query-provider/provider.rb +99 -0
- data/spec/attr_spec.rb +13 -0
- data/spec/autogeneration_spec.rb +29 -0
- data/spec/base_spec.rb +43 -0
- data/spec/constructor_spec.rb +10 -0
- data/spec/github_api_spec.rb +14 -0
- data/spec/lib/auto_generate_test_class.rb +6 -0
- data/spec/lib/github_commits.rb +10 -0
- data/spec/lib/github_user.rb +6 -0
- data/spec/lib/optional_where_test_class.rb +5 -0
- data/spec/lib/parameterless_auto_generate_test_class.rb +6 -0
- data/spec/lib/test_class.rb +5 -0
- data/spec/provider_spec.rb +16 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/where_spec.rb +32 -0
- metadata +155 -0
data/.document
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5
|
5
|
+
|
6
|
+
gem 'httparty'
|
7
|
+
gem 'json'
|
8
|
+
|
9
|
+
# Add dependencies to develop your gem here.
|
10
|
+
# Include everything needed to run rake, tests, features, etc.
|
11
|
+
group :development do
|
12
|
+
gem "rspec", ">= 0"
|
13
|
+
gem "rdoc", "~> 3.12"
|
14
|
+
gem "bundler", "~> 1.0.0"
|
15
|
+
gem "jeweler", "~> 1.8.3"
|
16
|
+
gem "simplecov", ">= 0"
|
17
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.3)
|
5
|
+
git (1.2.5)
|
6
|
+
httparty (0.8.1)
|
7
|
+
multi_json
|
8
|
+
multi_xml
|
9
|
+
jeweler (1.8.3)
|
10
|
+
bundler (~> 1.0)
|
11
|
+
git (>= 1.2.5)
|
12
|
+
rake
|
13
|
+
rdoc
|
14
|
+
json (1.6.5)
|
15
|
+
multi_json (1.1.0)
|
16
|
+
multi_xml (0.4.2)
|
17
|
+
rake (0.9.2.2)
|
18
|
+
rdoc (3.12)
|
19
|
+
json (~> 1.4)
|
20
|
+
rspec (2.8.0)
|
21
|
+
rspec-core (~> 2.8.0)
|
22
|
+
rspec-expectations (~> 2.8.0)
|
23
|
+
rspec-mocks (~> 2.8.0)
|
24
|
+
rspec-core (2.8.0)
|
25
|
+
rspec-expectations (2.8.0)
|
26
|
+
diff-lcs (~> 1.1.2)
|
27
|
+
rspec-mocks (2.8.0)
|
28
|
+
simplecov (0.6.1)
|
29
|
+
multi_json (~> 1.0)
|
30
|
+
simplecov-html (~> 0.5.3)
|
31
|
+
simplecov-html (0.5.3)
|
32
|
+
|
33
|
+
PLATFORMS
|
34
|
+
ruby
|
35
|
+
|
36
|
+
DEPENDENCIES
|
37
|
+
bundler (~> 1.0.0)
|
38
|
+
httparty
|
39
|
+
jeweler (~> 1.8.3)
|
40
|
+
json
|
41
|
+
rdoc (~> 3.12)
|
42
|
+
rspec
|
43
|
+
simplecov
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Femaref
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "api-query-provider"
|
18
|
+
gem.homepage = "http://github.com/Femaref/api-query-provider"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Provides an easy interface to arbitrary json apis}
|
21
|
+
gem.description = %Q{Provides an easy interface to arbitrary json apis}
|
22
|
+
gem.email = "femaref@googlemail.com"
|
23
|
+
gem.authors = ["Femaref"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
task :default => :spec
|
35
|
+
|
36
|
+
task :simplecov do
|
37
|
+
ENV['COVERAGE'] = "true"
|
38
|
+
Rake::Task[:spec].execute
|
39
|
+
end
|
40
|
+
|
41
|
+
require 'rdoc/task'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "api-query-provider #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
- improve ApiQueryProvider::Base.shadow (allow user defined aliasing)
|
2
|
+
- improve field definition on non autogenerated models (rename custom_fields -> field, allow call with no block for default behaviour)
|
3
|
+
- probably should split ApiQueryProvider::Base into Base and Object, Base serving as interaction layer, Object contains all field handling methods, would allow anonymous objects without much hassle
|
4
|
+
- improve ApiQueryProvider::Provider.system_symbols, should be a constant as it won't change at runtime
|
5
|
+
- think about ApiQueryProvider::Provider.execute, does it really need a forced array, could easily just return a single object
|
6
|
+
- ApiQueryProvider::Base.required_symbols should be cached, api_path shouldn't really change
|
7
|
+
- make configuration setters private, not needed to expose them
|
8
|
+
- ApiQueryProvider::Base should automatically try to create objects from nested hashes, also should iterate over arrays
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "api-query-provider"
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Femaref"]
|
12
|
+
s.date = "2012-04-21"
|
13
|
+
s.description = "Provides an easy interface to arbitrary json apis"
|
14
|
+
s.email = "femaref@googlemail.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc",
|
18
|
+
"TODO"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".travis.yml",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"LICENSE.txt",
|
26
|
+
"README.rdoc",
|
27
|
+
"Rakefile",
|
28
|
+
"TODO",
|
29
|
+
"VERSION",
|
30
|
+
"api-query-provider.gemspec",
|
31
|
+
"lib/api-query-provider.rb",
|
32
|
+
"lib/api-query-provider/base.rb",
|
33
|
+
"lib/api-query-provider/provider.rb",
|
34
|
+
"spec/attr_spec.rb",
|
35
|
+
"spec/autogeneration_spec.rb",
|
36
|
+
"spec/base_spec.rb",
|
37
|
+
"spec/constructor_spec.rb",
|
38
|
+
"spec/github_api_spec.rb",
|
39
|
+
"spec/lib/auto_generate_test_class.rb",
|
40
|
+
"spec/lib/github_commits.rb",
|
41
|
+
"spec/lib/github_user.rb",
|
42
|
+
"spec/lib/optional_where_test_class.rb",
|
43
|
+
"spec/lib/parameterless_auto_generate_test_class.rb",
|
44
|
+
"spec/lib/test_class.rb",
|
45
|
+
"spec/provider_spec.rb",
|
46
|
+
"spec/spec_helper.rb",
|
47
|
+
"spec/where_spec.rb"
|
48
|
+
]
|
49
|
+
s.homepage = "http://github.com/Femaref/api-query-provider"
|
50
|
+
s.licenses = ["MIT"]
|
51
|
+
s.require_paths = ["lib"]
|
52
|
+
s.rubygems_version = "1.8.10"
|
53
|
+
s.summary = "Provides an easy interface to arbitrary json apis"
|
54
|
+
|
55
|
+
if s.respond_to? :specification_version then
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0"])
|
60
|
+
s.add_runtime_dependency(%q<json>, [">= 0"])
|
61
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
62
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
63
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
64
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
65
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
68
|
+
s.add_dependency(%q<json>, [">= 0"])
|
69
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
70
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
71
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
72
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
73
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
74
|
+
end
|
75
|
+
else
|
76
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
77
|
+
s.add_dependency(%q<json>, [">= 0"])
|
78
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
79
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
80
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
81
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
82
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module ApiQueryProvider
|
2
|
+
# This class serves as a base class for any API Requests, it has several settings:
|
3
|
+
# +api_url+: sets the base url requests are made to_sym
|
4
|
+
# +api_path+: sets the path specific to this class, can contain replaceable elements
|
5
|
+
# +data_selector+: if the data is wrapped in an object, you can define a +Proc+ taking
|
6
|
+
# the parsed response as Hash and returning a portion of that Hash for further parsing
|
7
|
+
# the keys are +String+s.
|
8
|
+
# Be aware that if the data contains any fields named like a ruby internal method or field,
|
9
|
+
# it will be shadowed if you define it explicitly, it autogeneration is enabled, the name will
|
10
|
+
# have a underscore appended.
|
11
|
+
class Base
|
12
|
+
|
13
|
+
def self.api_url
|
14
|
+
@api_url
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.api_url= (value)
|
18
|
+
@api_url = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.api_path
|
22
|
+
@api_path
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.api_path= (value)
|
26
|
+
@api_path = value
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.required_symbols
|
30
|
+
@api_path.scan(/:(\w+)/).flatten.map { |e| e.to_sym } - ApiQueryProvider::Provider.system_symbols
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.data_selector
|
34
|
+
@data_selector || Proc.new { |e| e }
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.data_selector= (value)
|
38
|
+
@data_selector = value
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.autogenerate
|
42
|
+
if @autogenerate.nil?
|
43
|
+
false
|
44
|
+
else
|
45
|
+
@autogenerate
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.autogenerate= (value)
|
50
|
+
@autogenerate = value
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.custom_field(field, &block)
|
54
|
+
@custom_fields ||= {}
|
55
|
+
|
56
|
+
@custom_fields[field.to_sym] = block.to_proc
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.custom_fields
|
60
|
+
@custom_fields || {}
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.shadow(key)
|
64
|
+
key.to_sym == :class ? "class_".to_sym : key
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_reader :provided_symbols
|
68
|
+
|
69
|
+
|
70
|
+
# basic parsing constructor
|
71
|
+
# takes the json data and tries to assign it to +attr_accessor+ methods
|
72
|
+
# make sure to define them for any field present in the response
|
73
|
+
def initialize(data)
|
74
|
+
if self.class == ApiQueryProvider::Base
|
75
|
+
raise "this class should never be instanciated directly"
|
76
|
+
end
|
77
|
+
|
78
|
+
@provided_symbols = []
|
79
|
+
|
80
|
+
data.each do |key, value|
|
81
|
+
@provided_symbols << key.to_sym
|
82
|
+
|
83
|
+
key = self.class.shadow key
|
84
|
+
|
85
|
+
if !self.respond_to? key.to_sym
|
86
|
+
if self.class.autogenerate
|
87
|
+
self.class.class_eval do
|
88
|
+
attr_accessor key.to_sym
|
89
|
+
end
|
90
|
+
else
|
91
|
+
raise "field not found: #{key}. Either enable auto generation or add attr_accessor :#{key}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
if self.class.custom_fields.include? key.to_sym
|
96
|
+
value = self.class.custom_fields[key.to_sym].call(value)
|
97
|
+
end
|
98
|
+
|
99
|
+
self.send("#{key}=".to_sym, value)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def extend
|
104
|
+
if !(self.class.required_symbols - provided_symbols).empty?
|
105
|
+
raise "not all needed values are present"
|
106
|
+
end
|
107
|
+
|
108
|
+
request = self.class.where
|
109
|
+
|
110
|
+
self.class.required_symbols.each do |sym|
|
111
|
+
request = request.where(sym => self.send(self.class.shadow(sym).to_sym))
|
112
|
+
end
|
113
|
+
|
114
|
+
response = request.execute
|
115
|
+
|
116
|
+
if response.count != 1
|
117
|
+
raise "the request did not return exactly one element"
|
118
|
+
end
|
119
|
+
|
120
|
+
response.first
|
121
|
+
end
|
122
|
+
|
123
|
+
def extend!
|
124
|
+
local = self.extend
|
125
|
+
|
126
|
+
local.provided_symbols.each do |symbol|
|
127
|
+
shadow = self.class.shadow(symbol).to_sym
|
128
|
+
self.send("#{shadow}=".to_sym, local.send("#{shadow}".to_sym))
|
129
|
+
end
|
130
|
+
|
131
|
+
@provided_symbols = local.provided_symbols
|
132
|
+
|
133
|
+
self
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.interface
|
137
|
+
ApiQueryProvider::Provider.new(self)
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.where(opt = {})
|
141
|
+
interface.where(opt)
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.limit(count)
|
145
|
+
interface.limit(count)
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.select(*fields)
|
149
|
+
interface.select(fields)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module ApiQueryProvider
|
2
|
+
# Provides method chaining support
|
3
|
+
# replaces parameters in the api_path
|
4
|
+
# named parameters will be replaced by the assosicated value from where calls
|
5
|
+
# if a :where symbol is present in the string, any further values provided by where will be
|
6
|
+
# concatted to a key1=value,key2=value string and replaced there
|
7
|
+
# a value provided by limit will be replaced in to the :limit symbol
|
8
|
+
# if you can request additional fields or restrict the fields provided, place a :select symbol in the string
|
9
|
+
class Provider
|
10
|
+
attr_reader :where_constraints
|
11
|
+
attr_reader :count_constraint
|
12
|
+
attr_reader :select_fields
|
13
|
+
attr_reader :klass
|
14
|
+
|
15
|
+
def initialize (base)
|
16
|
+
api_url = base.api_url
|
17
|
+
api_path = base.api_path
|
18
|
+
if base.is_a? Class
|
19
|
+
@where_constraints = {}
|
20
|
+
@select_fields = []
|
21
|
+
@count_constraint = 0
|
22
|
+
@klass = base
|
23
|
+
else
|
24
|
+
@where_constraints = base.where_constraints
|
25
|
+
@select_fields = base.select_fields
|
26
|
+
@count_constraint = base.count_constraint
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def where(opt = {})
|
32
|
+
@where_constraints.merge! opt
|
33
|
+
|
34
|
+
return self
|
35
|
+
end
|
36
|
+
|
37
|
+
def limit(count)
|
38
|
+
@count_constraint = count
|
39
|
+
|
40
|
+
return self
|
41
|
+
end
|
42
|
+
|
43
|
+
def select(*fields)
|
44
|
+
@select_fields |= fields.flatten
|
45
|
+
|
46
|
+
return self
|
47
|
+
end
|
48
|
+
|
49
|
+
def replace_path
|
50
|
+
replaced_path = klass.api_path.dup
|
51
|
+
|
52
|
+
used_keys = []
|
53
|
+
|
54
|
+
@where_constraints.each do |key, value|
|
55
|
+
if replaced_path.gsub! /:#{key}/, value.to_s
|
56
|
+
used_keys << key
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
@where_constraints.reject! { |key, value| used_keys.include? key }
|
61
|
+
|
62
|
+
replaced_path.gsub! /:where/, @where_constraints.to_a.map { |e| e.join("=") }.join("&")
|
63
|
+
replaced_path.gsub! /:select/, @select_fields.join(",")
|
64
|
+
replaced_path.gsub! /:limit/, @count_constraint.to_s
|
65
|
+
|
66
|
+
if replaced_path.include?(":")
|
67
|
+
raise "you didn't replace all fields in the api_path"
|
68
|
+
end
|
69
|
+
|
70
|
+
replaced_path
|
71
|
+
end
|
72
|
+
|
73
|
+
def response
|
74
|
+
begin
|
75
|
+
uri = URI.join(klass.api_url, self.replace_path)
|
76
|
+
rescue
|
77
|
+
raise "invalid uri"
|
78
|
+
end
|
79
|
+
|
80
|
+
HTTParty.get(uri.to_s)
|
81
|
+
end
|
82
|
+
|
83
|
+
def execute
|
84
|
+
local_response = self.response
|
85
|
+
|
86
|
+
[klass.data_selector.call(JSON.parse(local_response.body))].flatten.map do |elem|
|
87
|
+
klass.new elem
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.interface
|
92
|
+
ApiQueryProvider::Provider.new(self)
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.system_symbols
|
96
|
+
[ :where, :count, :select ]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/spec/attr_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lib/test_class'
|
3
|
+
require 'lib/github_commits'
|
4
|
+
|
5
|
+
describe "ApiQueryProvider::Provider" do
|
6
|
+
it "should not replace api_url and api_path of two classes" do
|
7
|
+
TestClass.api_url.should == "http://example.com"
|
8
|
+
TestClass.api_path.should == "/foo/:id/id"
|
9
|
+
|
10
|
+
GithubCommits.api_url.should == "http://github.com/api/v2/json/"
|
11
|
+
GithubCommits.api_path.should == "commits/list/:user_id/:repository/:branch"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lib/auto_generate_test_class'
|
3
|
+
require 'lib/test_class'
|
4
|
+
|
5
|
+
describe AutoGenerateTestClass do
|
6
|
+
it "should auto generate fields" do
|
7
|
+
real = AutoGenerateTestClass.new({:foo => :bar})
|
8
|
+
|
9
|
+
real.respond_to?(:foo).should == true
|
10
|
+
real.respond_to?(:bar).should == false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe TestClass do
|
15
|
+
it "should raise exception encountering a non existant field" do
|
16
|
+
lambda { real = TestClass.new({:foo => :bar}) }.should raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO move to own test
|
20
|
+
it "should return :id as required symbol" do
|
21
|
+
TestClass.required_symbols.should == [ :id ]
|
22
|
+
end
|
23
|
+
|
24
|
+
# TODO move to own test
|
25
|
+
it "should raise on non-replaced mandatory field" do
|
26
|
+
lambda { TestClass.where().replace_path }.should raise_error(Exception, "you didn't replace all fields in the api_path")
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lib/auto_generate_test_class'
|
3
|
+
require 'lib/parameterless_auto_generate_test_class'
|
4
|
+
|
5
|
+
describe ApiQueryProvider::Base do
|
6
|
+
it "should raise an exception being instanciated directly" do
|
7
|
+
lambda { real = ApiQueryProvider::Base.new({}) }.should raise_error(Exception, "this class should never be instanciated directly")
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should not be manipulated if a deriving class is manipulated" do
|
11
|
+
AutoGenerateTestClass.new({:foo => :bar})
|
12
|
+
|
13
|
+
ApiQueryProvider::Base.instance_methods.include?(:foo).should == false
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "extend" do
|
17
|
+
it "should raise on missing symbol" do
|
18
|
+
real = AutoGenerateTestClass.new({})
|
19
|
+
|
20
|
+
lambda { real.extend }.should raise_error(Exception, "not all needed values are present")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should allow parameterless api calls" do
|
24
|
+
HTTParty.stub(:get) { double(:body => %q({ "id" : "1", "name": "test" })) }
|
25
|
+
|
26
|
+
real = ParameterlessAutoGenerateTestClass.new({})
|
27
|
+
|
28
|
+
lambda { real.extend }.should_not raise_error
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "extend!" do
|
33
|
+
it "should copy additional fields to the current object" do
|
34
|
+
HTTParty.stub(:get) { double(:body => %q({ "id" : "1", "name": "test" })) }
|
35
|
+
|
36
|
+
real = AutoGenerateTestClass.new({:id => 1})
|
37
|
+
|
38
|
+
real.extend!
|
39
|
+
|
40
|
+
real.name.should == "test"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lib/github_commits'
|
3
|
+
require 'lib/github_user'
|
4
|
+
|
5
|
+
describe "github commit api" do
|
6
|
+
it "should construct a valid object" do
|
7
|
+
lambda do
|
8
|
+
GithubCommits.where(:user_id => "Femaref")
|
9
|
+
.where(:repository => "c2dm-rails")
|
10
|
+
.where(:branch => "master")
|
11
|
+
.execute
|
12
|
+
end.should_not raise_error
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class GithubCommits < ApiQueryProvider::Base
|
2
|
+
self.api_url = "http://github.com/api/v2/json/"
|
3
|
+
self.api_path = "commits/list/:user_id/:repository/:branch"
|
4
|
+
self.data_selector = Proc.new {|element| element["commits"] }
|
5
|
+
self.autogenerate = true
|
6
|
+
|
7
|
+
self.custom_field :author do |input|
|
8
|
+
GithubUser.new input
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lib/auto_generate_test_class'
|
3
|
+
|
4
|
+
# uses the auto generation test class as interface
|
5
|
+
|
6
|
+
describe AutoGenerateTestClass do
|
7
|
+
it "should not modify @api_path" do
|
8
|
+
HTTParty.stub(:get) { double(:body => %q({ "id" : "1", "name": "test" })) }
|
9
|
+
|
10
|
+
real = AutoGenerateTestClass.api_path.dup
|
11
|
+
|
12
|
+
AutoGenerateTestClass.where(:id => 1).execute
|
13
|
+
|
14
|
+
AutoGenerateTestClass.api_path.should == real
|
15
|
+
end
|
16
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'simplecov'
|
5
|
+
|
6
|
+
module SimpleCov::Configuration
|
7
|
+
def clean_filters
|
8
|
+
@filters = []
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
SimpleCov.configure do
|
13
|
+
clean_filters
|
14
|
+
load_adapter 'test_frameworks'
|
15
|
+
end
|
16
|
+
|
17
|
+
ENV["COVERAGE"] && SimpleCov.start do
|
18
|
+
add_filter "/.rvm/"
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
require 'rspec'
|
23
|
+
require 'api-query-provider'
|
24
|
+
|
25
|
+
# Requires supporting files with custom matchers and macros, etc,
|
26
|
+
# in ./support/ and its subdirectories.
|
27
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
28
|
+
|
29
|
+
RSpec.configure do |config|
|
30
|
+
|
31
|
+
end
|
data/spec/where_spec.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lib/test_class'
|
3
|
+
require 'lib/optional_where_test_class'
|
4
|
+
|
5
|
+
describe "Where" do
|
6
|
+
it "should merge the where_constraint hash" do
|
7
|
+
real = TestClass.where(:id => 1).where(:name => "foo")
|
8
|
+
|
9
|
+
real.where_constraints.should == ({ :id => 1, :name => "foo" })
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should replace only symbols" do
|
13
|
+
real = TestClass.where(:id => 1)
|
14
|
+
|
15
|
+
real.replace_path.should == "/foo/1/id"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should not add non-defined symbol values" do
|
19
|
+
real = TestClass.where(:id => 1, :name => "something")
|
20
|
+
|
21
|
+
real.replace_path.should == "/foo/1/id"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe OptionalWhereTestClass do
|
26
|
+
it "should replace optional :where symbol" do
|
27
|
+
real = OptionalWhereTestClass.where(:ref_id => 1, :ref_type => 2)
|
28
|
+
|
29
|
+
real.replace_path.should == "/foo/?ref_id=1&ref_type=2"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: api-query-provider
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Femaref
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: &70154304918460 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70154304918460
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: json
|
27
|
+
requirement: &70154304917980 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70154304917980
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &70154304917500 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70154304917500
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rdoc
|
49
|
+
requirement: &70154304917020 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.12'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70154304917020
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: bundler
|
60
|
+
requirement: &70154304916540 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.0.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70154304916540
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: jeweler
|
71
|
+
requirement: &70154304916060 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.8.3
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70154304916060
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: simplecov
|
82
|
+
requirement: &70154304915580 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70154304915580
|
91
|
+
description: Provides an easy interface to arbitrary json apis
|
92
|
+
email: femaref@googlemail.com
|
93
|
+
executables: []
|
94
|
+
extensions: []
|
95
|
+
extra_rdoc_files:
|
96
|
+
- LICENSE.txt
|
97
|
+
- README.rdoc
|
98
|
+
- TODO
|
99
|
+
files:
|
100
|
+
- .document
|
101
|
+
- .travis.yml
|
102
|
+
- Gemfile
|
103
|
+
- Gemfile.lock
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.rdoc
|
106
|
+
- Rakefile
|
107
|
+
- TODO
|
108
|
+
- VERSION
|
109
|
+
- api-query-provider.gemspec
|
110
|
+
- lib/api-query-provider.rb
|
111
|
+
- lib/api-query-provider/base.rb
|
112
|
+
- lib/api-query-provider/provider.rb
|
113
|
+
- spec/attr_spec.rb
|
114
|
+
- spec/autogeneration_spec.rb
|
115
|
+
- spec/base_spec.rb
|
116
|
+
- spec/constructor_spec.rb
|
117
|
+
- spec/github_api_spec.rb
|
118
|
+
- spec/lib/auto_generate_test_class.rb
|
119
|
+
- spec/lib/github_commits.rb
|
120
|
+
- spec/lib/github_user.rb
|
121
|
+
- spec/lib/optional_where_test_class.rb
|
122
|
+
- spec/lib/parameterless_auto_generate_test_class.rb
|
123
|
+
- spec/lib/test_class.rb
|
124
|
+
- spec/provider_spec.rb
|
125
|
+
- spec/spec_helper.rb
|
126
|
+
- spec/where_spec.rb
|
127
|
+
homepage: http://github.com/Femaref/api-query-provider
|
128
|
+
licenses:
|
129
|
+
- MIT
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
segments:
|
141
|
+
- 0
|
142
|
+
hash: -771518329520128874
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
145
|
+
requirements:
|
146
|
+
- - ! '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 1.8.10
|
152
|
+
signing_key:
|
153
|
+
specification_version: 3
|
154
|
+
summary: Provides an easy interface to arbitrary json apis
|
155
|
+
test_files: []
|