vkontakte_api 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +95 -0
- data/README.ru.md +95 -0
- data/Rakefile +13 -0
- data/lib/vkontakte_api.rb +19 -0
- data/lib/vkontakte_api/api.rb +28 -0
- data/lib/vkontakte_api/client.rb +18 -0
- data/lib/vkontakte_api/configuration.rb +22 -0
- data/lib/vkontakte_api/error.rb +27 -0
- data/lib/vkontakte_api/namespaces.yml +22 -0
- data/lib/vkontakte_api/resolver.rb +91 -0
- data/lib/vkontakte_api/version.rb +3 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/vkontakte_api/api_spec.rb +83 -0
- data/spec/vkontakte_api/client_spec.rb +54 -0
- data/spec/vkontakte_api/configuration_spec.rb +29 -0
- data/spec/vkontakte_api/error_spec.rb +37 -0
- data/spec/vkontakte_api/resolver_spec.rb +169 -0
- data/spec/vkontakte_api_spec.rb +14 -0
- data/vkontakte_api.gemspec +28 -0
- metadata +170 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Vsevolod Romashov
|
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.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# vkontakte_api
|
2
|
+
|
3
|
+
`vkontakte_api` is a Ruby wrapper for VKontakte API. It allows you to call all API methods in the simplest possible way.
|
4
|
+
|
5
|
+
Below is the English version of the readme. Russian version is located [here](https://github.com/7even/vkontakte_api/blob/master/README.ru.md).
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
``` bash
|
10
|
+
gem install vkontakte_api
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
Default HTTP request library is `Net::HTTP`. You can set any other adapter supported by `faraday` in the configure block like so:
|
16
|
+
|
17
|
+
``` ruby
|
18
|
+
VkontakteApi.configure do |config|
|
19
|
+
config.adapter = :net_http
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
All requests are sent via `VkontakteApi::Client` instance. To create one you just pass an access token.
|
24
|
+
|
25
|
+
``` ruby
|
26
|
+
@app = VkontakteApi::Client.new('my_access_token')
|
27
|
+
```
|
28
|
+
|
29
|
+
Probably the easiest way to get an access token in a web-app is using [OmniAuth](https://github.com/intridea/omniauth), but you can roll your own authentication if for some reason `OmniAuth` isn't acceptable. Currently `vkontakte_api` doesn't offer authentication functionality.
|
30
|
+
|
31
|
+
Now you can call the API methods. All method names are underscore_cased as opposed to the [official documentation](http://vk.com/developers.php?oid=-17680044&p=API_Method_Description) where they are camelCased, so `getGroups` becomes `get_groups`. You can still call them in a camelCased manner, but that is not a Ruby-way practice.
|
32
|
+
|
33
|
+
``` ruby
|
34
|
+
@app.get_user_settings # => 327710
|
35
|
+
@app.groups.get # => [1, 31022447]
|
36
|
+
```
|
37
|
+
|
38
|
+
Predicate methods (those which begin with `is`, like `is_app_user`) are expected to return the result of some condition, so the '?' is appended to the end of the method name, and they return `true` or `false`:
|
39
|
+
|
40
|
+
``` ruby
|
41
|
+
@app.is_app_user? # => true
|
42
|
+
```
|
43
|
+
|
44
|
+
You can still call these without a '?' and get `'1'` or `'0'` in result if you want to handle that yourself.
|
45
|
+
|
46
|
+
Now for parameters. All method parameters are named, and you can pass them in a hash where parameter names are keys and parameter values are values:
|
47
|
+
|
48
|
+
``` ruby
|
49
|
+
@app.friends.get(fields: 'uid,first_name,last_name')
|
50
|
+
# => [
|
51
|
+
{
|
52
|
+
:uid => "1",
|
53
|
+
:first_name => "Павел",
|
54
|
+
:last_name => "Дуров"
|
55
|
+
},
|
56
|
+
{
|
57
|
+
:uid => "6492",
|
58
|
+
:first_name => "Andrew",
|
59
|
+
:last_name => "Rogozov"
|
60
|
+
}
|
61
|
+
]
|
62
|
+
```
|
63
|
+
|
64
|
+
It's also worth noting that all returned hashes have symbolized keys.
|
65
|
+
|
66
|
+
If the response is an Enumerable, you can pass a block that will yield each successive element and put the result in the returned array (like `Enumerable#map` does):
|
67
|
+
|
68
|
+
``` ruby
|
69
|
+
@app.friends.get(fields: 'first_name,last_name') do |friend|
|
70
|
+
"#{friend[:first_name]} #{friend[:last_name]}"
|
71
|
+
end
|
72
|
+
# => ["Павел Дуров", "Andrew Rogozov"]
|
73
|
+
```
|
74
|
+
|
75
|
+
`vkontakte_api` doesn't keep any method names list inside (except method namespaces like `friends` or `groups`) - when you call a method, it's name is camelcased before sending a request to VKontakte. So when a new method is added to the API, you don't need to wait for the new version of `vkontakte_api` gem - you can use that new method immediately. If you mistype the method name or use a method you don't have rights to call, you will get an exception with a relevant message (more about the exceptions below).
|
76
|
+
|
77
|
+
### Error handling
|
78
|
+
|
79
|
+
If VKontakte returns an error in response, you get a `VkontakteApi::Error` exception with all meaningful information that can be retrieved:
|
80
|
+
|
81
|
+
``` ruby
|
82
|
+
@app.audio.get_by_id
|
83
|
+
# => VkontakteApi::Error: VKontakte returned an error 1: 'Unknown error occured' after calling method 'audio.getById' with parameters {}.
|
84
|
+
```
|
85
|
+
|
86
|
+
## Roadmap
|
87
|
+
|
88
|
+
* Authentication (getting the access_token from VK)
|
89
|
+
* RDoc coverage
|
90
|
+
|
91
|
+
## Contributing
|
92
|
+
|
93
|
+
If you want to contribute to the project, fork the repository, push your changes to a topic branch and send me a pull request.
|
94
|
+
|
95
|
+
`vkontakte_api` is tested under MRI `1.8.7`, `1.9.2` and `1.9.3`. If something is working incorrectly or not working at all in one of these environments, this should be considered a bug. Any bug reports are welcome at Github issues.
|
data/README.ru.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# vkontakte_api
|
2
|
+
|
3
|
+
`vkontakte_api` - ruby-обертка для API ВКонтакте. Она позволяет вызывать методы API настолько просто, насколько это возможно.
|
4
|
+
|
5
|
+
Это русская версия readme. Английская версия лежит [здесь](https://github.com/7even/vkontakte_api/blob/master/README.md).
|
6
|
+
|
7
|
+
## Установка
|
8
|
+
|
9
|
+
``` bash
|
10
|
+
gem install vkontakte_api
|
11
|
+
```
|
12
|
+
|
13
|
+
## Использование
|
14
|
+
|
15
|
+
По умолчанию для HTTP-запросов используется `Net::HTTP`. Можно выбрать любой другой адаптер, поддерживаемый `faraday`, в блоке `VkontakteApi.configure` следующим образом:
|
16
|
+
|
17
|
+
``` ruby
|
18
|
+
VkontakteApi.configure do |config|
|
19
|
+
config.adapter = :net_http
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
Все запросы к API отправляются через объект класса `VkontakteApi::Client`. Чтобы создать его, нужно просто передать в конструктор токен доступа.
|
24
|
+
|
25
|
+
``` ruby
|
26
|
+
@app = VkontakteApi::Client.new('my_access_token')
|
27
|
+
```
|
28
|
+
|
29
|
+
Пожалуй, самый простой способ получить токен в веб-приложении - использовать [OmniAuth](https://github.com/intridea/omniauth), но если это неприемлемо, можно реализовать свой механизм авторизации. На данный момент `vkontakte_api` не умеет получать токен.
|
30
|
+
|
31
|
+
Теперь можно вызывать методы API. Все названия методов переведены в underscore_case - в отличие от [официальной документации](http://vk.com/developers.php?oid=-17680044&p=API_Method_Description), где они в camelCase, т.е. `getGroups` становится `get_groups`. Можно по прежнему писать методы в camelCase, но это не соответствует стандартам стиля кода, принятым в ruby.
|
32
|
+
|
33
|
+
``` ruby
|
34
|
+
@app.get_user_settings # => 327710
|
35
|
+
@app.groups.get # => [1, 31022447]
|
36
|
+
```
|
37
|
+
|
38
|
+
Предикатные методы (названия которых начинаются с `is`, например `is_app_user`) должны возвращать результат какого-то условия, поэтому в конец названия метода добавляется '?', и возвращается булево значение (`true` или `false`):
|
39
|
+
|
40
|
+
``` ruby
|
41
|
+
@app.is_app_user? # => true
|
42
|
+
```
|
43
|
+
|
44
|
+
Можно вызывать эти методы и без '?' на конце, тогда они будут возвращать `'0'` или `'1'`.
|
45
|
+
|
46
|
+
Теперь о параметрах. Все параметры именованные, и передаются в методы в виде хэша, где ключи соответствуют названиям параметров, а значения - соответственно, их значениям:
|
47
|
+
|
48
|
+
``` ruby
|
49
|
+
@app.friends.get(fields: 'uid,first_name,last_name')
|
50
|
+
# => [
|
51
|
+
{
|
52
|
+
:uid => "1",
|
53
|
+
:first_name => "Павел",
|
54
|
+
:last_name => "Дуров"
|
55
|
+
},
|
56
|
+
{
|
57
|
+
:uid => "6492",
|
58
|
+
:first_name => "Andrew",
|
59
|
+
:last_name => "Rogozov"
|
60
|
+
}
|
61
|
+
]
|
62
|
+
```
|
63
|
+
|
64
|
+
Также следует заметить, что все возвращаемые хэши имеют символьные ключи.
|
65
|
+
|
66
|
+
Если результат метода - Enumerable, то методу можно передать блок, который будет вызван для каждого элемента результата. В этом случае метод вернет массив из результатов выполнения блока с каждым элементом (аналогично `Enumerable#map`):
|
67
|
+
|
68
|
+
``` ruby
|
69
|
+
@app.friends.get(fields: 'first_name,last_name') do |friend|
|
70
|
+
"#{friend[:first_name]} #{friend[:last_name]}"
|
71
|
+
end
|
72
|
+
# => ["Павел Дуров", "Andrew Rogozov"]
|
73
|
+
```
|
74
|
+
|
75
|
+
`vkontakte_api` не содержит списка названий методов (если не считать пространств имен, вроде `friends` или `groups`) - когда вызывается метод, его название переводится в camelCase, а уже потом отправляется запрос к ВКонтакте. Поэтому когда новый метод добавляется в API, не нужно ждать новой версии гема `vkontakte_api` - можно использовать этот новый метод сразу же. Если в названии запрошенного метода допущены ошибки, или вызван метод, на выполнение которого отсутствуют права, будет выброшено исключение с соответствующим сообщением (об исключениях чуть ниже).
|
76
|
+
|
77
|
+
### Обработка ошибок
|
78
|
+
|
79
|
+
Если ВКонтакте возвращает ошибку, выбрасывается исключение класса `VkontakteApi::Error` со всей значимой информацией, которую можно получить:
|
80
|
+
|
81
|
+
``` ruby
|
82
|
+
@app.audio.get_by_id
|
83
|
+
# => VkontakteApi::Error: VKontakte returned an error 1: 'Unknown error occured' after calling method 'audio.getById' with parameters {}.
|
84
|
+
```
|
85
|
+
|
86
|
+
## Планы
|
87
|
+
|
88
|
+
* Авторизация (получение токена доступа с ВКонтакте)
|
89
|
+
* Документация RDoc
|
90
|
+
|
91
|
+
## Участие в разработке
|
92
|
+
|
93
|
+
Если вы хотите поучаствовать в разработке проекта, форкните репозиторий, положите свои изменения в отдельную ветку и отправьте мне pull request.
|
94
|
+
|
95
|
+
`vkontakte_api` тестируется под MRI `1.8.7`, `1.9.2` и `1.9.3`. Если в одной из этих сред что-то работает неправильно, либо вообще не работает, то это следует считать багом, и написать об этом в issues на Github.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
desc 'Fires up the console with preloaded vkontakte_api'
|
4
|
+
task :console do
|
5
|
+
sh 'pry -I ./lib/ -r ./lib/vkontakte_api.rb'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
RSpec::Core::RakeTask.new do |t|
|
10
|
+
t.rspec_opts = '--color --format doc'
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :spec
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'yajl'
|
3
|
+
require 'yaml'
|
4
|
+
require 'active_support/core_ext/string/inflections'
|
5
|
+
require 'active_support/core_ext/object/to_query'
|
6
|
+
|
7
|
+
require 'vkontakte_api/version'
|
8
|
+
require 'vkontakte_api/error'
|
9
|
+
require 'vkontakte_api/configuration'
|
10
|
+
require 'vkontakte_api/api'
|
11
|
+
require 'vkontakte_api/resolver'
|
12
|
+
require 'vkontakte_api/client'
|
13
|
+
|
14
|
+
module VkontakteApi
|
15
|
+
extend VkontakteApi::Configuration
|
16
|
+
end
|
17
|
+
|
18
|
+
# short alias
|
19
|
+
VK = VkontakteApi unless defined?(VK)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module VkontakteApi
|
2
|
+
module API
|
3
|
+
BASE_HOST = 'https://api.vkontakte.ru'
|
4
|
+
BASE_URL = '/method/'
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def call(method_name, args = {}, &block)
|
8
|
+
connection = Faraday.new(:url => BASE_HOST) do |builder|
|
9
|
+
builder.adapter(VkontakteApi.adapter)
|
10
|
+
end
|
11
|
+
|
12
|
+
url = url_for(method_name, args)
|
13
|
+
body = connection.get(url).body
|
14
|
+
response = Yajl::Parser.parse(body, :symbolize_keys => true)
|
15
|
+
|
16
|
+
if response.has_key?(:error)
|
17
|
+
raise VkontakteApi::Error.new(response[:error])
|
18
|
+
else
|
19
|
+
response[:response]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
private
|
23
|
+
def url_for(method_name, args)
|
24
|
+
"#{BASE_URL}#{method_name}?#{args.to_param}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module VkontakteApi
|
2
|
+
class Client
|
3
|
+
attr_reader :access_token
|
4
|
+
|
5
|
+
def initialize(access_token = nil)
|
6
|
+
@access_token = access_token
|
7
|
+
end
|
8
|
+
|
9
|
+
def authorized?
|
10
|
+
!@access_token.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(method_name, *args, &block)
|
14
|
+
args = args.first || {}
|
15
|
+
VkontakteApi::Resolver.new(:access_token => @access_token).send(method_name, args, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module VkontakteApi
|
2
|
+
module Configuration
|
3
|
+
OPTION_NAMES = [:app_id, :app_secret, :adapter]
|
4
|
+
|
5
|
+
attr_accessor *OPTION_NAMES
|
6
|
+
|
7
|
+
DEFAULT_ADAPTER = :net_http
|
8
|
+
|
9
|
+
def configure
|
10
|
+
yield self if block_given?
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
15
|
+
@adapter = DEFAULT_ADAPTER
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.extended(base)
|
19
|
+
base.reset
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module VkontakteApi
|
2
|
+
class Error < StandardError
|
3
|
+
def initialize(data)
|
4
|
+
@error_code = data.delete(:error_code)
|
5
|
+
@error_msg = data.delete(:error_msg)
|
6
|
+
@params = {}
|
7
|
+
|
8
|
+
request_params = parse_params(data.delete :request_params)
|
9
|
+
|
10
|
+
@method_name = request_params.delete('method')
|
11
|
+
@access_token = request_params.delete('access_token')
|
12
|
+
@oauth = request_params.delete('oauth')
|
13
|
+
@params = request_params
|
14
|
+
end
|
15
|
+
|
16
|
+
def message
|
17
|
+
"VKontakte returned an error #{@error_code}: \'#{@error_msg}\' after calling method \'#{@method_name}\' with parameters #{@params.inspect}."
|
18
|
+
end
|
19
|
+
private
|
20
|
+
def parse_params(params)
|
21
|
+
params.inject({}) do |memo, pair|
|
22
|
+
memo[pair[:key]] = pair[:value]
|
23
|
+
memo
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
- friends
|
2
|
+
- groups
|
3
|
+
- photos
|
4
|
+
- wall
|
5
|
+
- newsfeed
|
6
|
+
- notifications
|
7
|
+
- audio
|
8
|
+
- video
|
9
|
+
- docs
|
10
|
+
- places
|
11
|
+
- secure
|
12
|
+
- storage
|
13
|
+
- notes
|
14
|
+
- pages
|
15
|
+
- activity
|
16
|
+
- offers
|
17
|
+
- questions
|
18
|
+
- subscriptions
|
19
|
+
- messages
|
20
|
+
- likes
|
21
|
+
- status
|
22
|
+
- polls
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module VkontakteApi
|
2
|
+
class Resolver
|
3
|
+
PREDICATE_NAMES = /^(is.*)\?$/
|
4
|
+
|
5
|
+
attr_reader :namespace
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@namespace = options.delete(:namespace)
|
9
|
+
@access_token = options.delete(:access_token)
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(method_name, *args, &block)
|
13
|
+
method_name = method_name.to_s
|
14
|
+
|
15
|
+
if Resolver.namespaces.include?(method_name)
|
16
|
+
# method with a two-level name called
|
17
|
+
Resolver.new(:namespace => method_name, :access_token => @access_token)
|
18
|
+
else
|
19
|
+
# method with a one-level name called
|
20
|
+
name, type = Resolver.vk_method_name(method_name, @namespace)
|
21
|
+
|
22
|
+
# adding access_token to the args hash
|
23
|
+
args = args.first || {}
|
24
|
+
args.update(:access_token => @access_token)
|
25
|
+
|
26
|
+
result = API.call(name, args, &block)
|
27
|
+
|
28
|
+
if result.respond_to?(:each)
|
29
|
+
# enumerable result receives :map with a block when called with a block
|
30
|
+
# or is returned untouched otherwise
|
31
|
+
block_given? ? result.map(&block) : result
|
32
|
+
else
|
33
|
+
# non-enumerable result is typecasted
|
34
|
+
# (and yielded if block_given?)
|
35
|
+
result = typecast(result, type)
|
36
|
+
block_given? ? yield(result) : result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
private
|
41
|
+
def typecast(parameter, type)
|
42
|
+
case type
|
43
|
+
when :boolean
|
44
|
+
# '1' becomes true, '0' becomes false
|
45
|
+
!parameter.to_i.zero?
|
46
|
+
else
|
47
|
+
parameter
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
attr_reader :namespaces
|
53
|
+
|
54
|
+
# load namespaces array from namespaces.yml
|
55
|
+
def load_namespaces
|
56
|
+
filename = File.expand_path('../namespaces.yml', __FILE__)
|
57
|
+
file = File.read(filename)
|
58
|
+
@namespaces = YAML.load(file)
|
59
|
+
end
|
60
|
+
|
61
|
+
# vk_method_name('get_country_by_id', 'places')
|
62
|
+
# => 'places.getCountryById'
|
63
|
+
def vk_method_name(method_name, namespace = nil)
|
64
|
+
method_name = method_name.to_s
|
65
|
+
|
66
|
+
if method_name =~ PREDICATE_NAMES
|
67
|
+
# predicate methods should return true or false
|
68
|
+
method_name.sub!(PREDICATE_NAMES, '\1')
|
69
|
+
type = :boolean
|
70
|
+
else
|
71
|
+
# other methods can return anything they want
|
72
|
+
type = :anything
|
73
|
+
end
|
74
|
+
|
75
|
+
full_name = ''
|
76
|
+
full_name << convert(namespace) + '.' unless namespace.nil?
|
77
|
+
full_name << convert(method_name)
|
78
|
+
|
79
|
+
[full_name, type]
|
80
|
+
end
|
81
|
+
private
|
82
|
+
# convert('get_profiles')
|
83
|
+
# => 'getProfiles'
|
84
|
+
def convert(name)
|
85
|
+
name.camelize(:lower)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
VkontakteApi::Resolver.load_namespaces
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VkontakteApi::API do
|
4
|
+
before(:each) do
|
5
|
+
@method_name = 'apiMethod'
|
6
|
+
@args = {
|
7
|
+
:field => 'value',
|
8
|
+
:access_token => 'some_token'
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".call" do
|
13
|
+
before(:each) do
|
14
|
+
@url = stub("URL")
|
15
|
+
VkontakteApi::API.stub(:url_for).and_return(@url)
|
16
|
+
|
17
|
+
@connection = stub("Faraday connection")
|
18
|
+
Faraday.stub(:new).and_return(@connection)
|
19
|
+
|
20
|
+
body = stub("Response body")
|
21
|
+
response = stub("Response", :body => body)
|
22
|
+
@connection.stub(:get).and_return(response)
|
23
|
+
|
24
|
+
@result = stub("Result")
|
25
|
+
@result.stub(:has_key?) do |key|
|
26
|
+
if key == 'response'
|
27
|
+
true
|
28
|
+
else
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@result_response = stub("Result[response]")
|
34
|
+
@result_error = stub("Result[error]").as_null_object
|
35
|
+
|
36
|
+
@result.stub(:[]) do |key|
|
37
|
+
if key == :response
|
38
|
+
@result_response
|
39
|
+
else
|
40
|
+
@result_error
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Yajl::Parser.stub(:parse).and_return(@result)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "calls the url from .url_for" do
|
48
|
+
@connection.should_receive(:get).with(@url)
|
49
|
+
VkontakteApi::API.call('apiMethod')
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with a successful response" do
|
53
|
+
it "returns the response body" do
|
54
|
+
VkontakteApi::API.call('apiMethod').should == @result_response
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with an error response" do
|
59
|
+
before(:each) do
|
60
|
+
@result.stub(:has_key?) do |key|
|
61
|
+
if key == 'response'
|
62
|
+
false
|
63
|
+
else
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "raises a VkontakteApi::Error" do
|
70
|
+
expect {
|
71
|
+
VkontakteApi::API.call('apiMethod')
|
72
|
+
}.to raise_error(VkontakteApi::Error)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe ".url_for" do
|
78
|
+
it "constructs a valid VK API url" do
|
79
|
+
url = VkontakteApi::API.send(:url_for, @method_name, @args)
|
80
|
+
url.should == '/method/apiMethod?access_token=some_token&field=value'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VkontakteApi::Client do
|
4
|
+
before(:each) do
|
5
|
+
@token = stub("Access token")
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#initialize" do
|
9
|
+
context "without arguments" do
|
10
|
+
it "creates a client with a nil access_token" do
|
11
|
+
VkontakteApi::Client.new.access_token.should be_nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with a token argument" do
|
16
|
+
it "creates a client with a given access_token" do
|
17
|
+
client = VkontakteApi::Client.new(@token)
|
18
|
+
client.access_token.should == @token
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#authorized?" do
|
24
|
+
context "with an unauthorized client" do
|
25
|
+
it "returns false" do
|
26
|
+
VkontakteApi::Client.new.should_not be_authorized
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with an authorized client" do
|
31
|
+
it "returns true" do
|
32
|
+
VkontakteApi::Client.new(@token).should be_authorized
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#method_missing" do
|
38
|
+
before(:each) do
|
39
|
+
@resolver = stub("Resolver").as_null_object
|
40
|
+
VkontakteApi::Resolver.stub(:new).and_return(@resolver)
|
41
|
+
@args = {:field => 'value'}
|
42
|
+
end
|
43
|
+
|
44
|
+
it "creates a resolver, passing it the access_token" do
|
45
|
+
VkontakteApi::Resolver.should_receive(:new).with(:access_token => @token)
|
46
|
+
VkontakteApi::Client.new(@token).api_method(@args)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "delegates to VkontakteApi::Resolver" do
|
50
|
+
@resolver.should_receive(:api_method).with(@args)
|
51
|
+
VkontakteApi::Client.new(@token).api_method(@args)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Configurable
|
4
|
+
extend VkontakteApi::Configuration
|
5
|
+
end
|
6
|
+
|
7
|
+
describe VkontakteApi::Configuration do
|
8
|
+
describe "#configure" do
|
9
|
+
it "yields self" do
|
10
|
+
Configurable.should_receive(:some_method)
|
11
|
+
Configurable.configure do |config|
|
12
|
+
config.some_method
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "returns self" do
|
17
|
+
Configurable.configure.should == Configurable
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#reset" do
|
22
|
+
it "sets all options to their default values" do
|
23
|
+
Configurable.reset
|
24
|
+
Configurable.app_id.should be_nil
|
25
|
+
Configurable.app_secret.should be_nil
|
26
|
+
Configurable.adapter.should == VkontakteApi::Configuration::DEFAULT_ADAPTER
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VkontakteApi::Error do
|
4
|
+
before(:each) do
|
5
|
+
@e = VkontakteApi::Error.new(
|
6
|
+
:error_code => 5,
|
7
|
+
:error_msg => 'User authorization failed: invalid access_token.',
|
8
|
+
:request_params => [
|
9
|
+
{
|
10
|
+
:key => 'oauth',
|
11
|
+
:value => '1'
|
12
|
+
},
|
13
|
+
{
|
14
|
+
:key => 'method',
|
15
|
+
:value => 'unknownMethod'
|
16
|
+
},
|
17
|
+
{
|
18
|
+
:key => 'some',
|
19
|
+
:value => 'params'
|
20
|
+
},
|
21
|
+
{
|
22
|
+
:key => 'access_token',
|
23
|
+
:value => '123'
|
24
|
+
}
|
25
|
+
]
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#message" do
|
30
|
+
it "returns all needed data about an error" do
|
31
|
+
message = 'VKontakte returned an error 5: \'User authorization failed: invalid access_token.\' after calling method \'unknownMethod\' with parameters {"some"=>"params"}.'
|
32
|
+
expect {
|
33
|
+
raise @e
|
34
|
+
}.to raise_error(@e.class, message)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VkontakteApi::Resolver do
|
4
|
+
describe "#method_missing" do
|
5
|
+
before(:each) do
|
6
|
+
@result = stub("API result")
|
7
|
+
@result.stub(:respond_to?).and_return(false)
|
8
|
+
|
9
|
+
VkontakteApi::API.stub(:call).and_return(@result)
|
10
|
+
@args = {:arg_name => 'arg_value'}
|
11
|
+
@token = stub("Access token")
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with a nil @namespace" do
|
15
|
+
before(:each) do
|
16
|
+
@resolver = VkontakteApi::Resolver.new(:access_token => @token)
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with method_name not from NAMESPACES" do
|
20
|
+
before(:each) do
|
21
|
+
VkontakteApi::Resolver.stub(:vk_method_name).and_return(['apiMethod', :anything])
|
22
|
+
end
|
23
|
+
|
24
|
+
it "calls #vk_method_name with method name and nil namespace" do
|
25
|
+
VkontakteApi::Resolver.should_receive(:vk_method_name).with('api_method', nil)
|
26
|
+
@resolver.api_method
|
27
|
+
end
|
28
|
+
|
29
|
+
it "calls #api_call with full VK method name" do
|
30
|
+
full_args = @args.merge(:access_token => @token)
|
31
|
+
VkontakteApi::API.should_receive(:call).with('apiMethod', full_args)
|
32
|
+
@resolver.api_method(@args).should == @result
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with method_name from NAMESPACES" do
|
37
|
+
it "return a new resolver with the corresponding @namespace" do
|
38
|
+
new_resolver = @resolver.friends
|
39
|
+
new_resolver.should be_a(VkontakteApi::Resolver)
|
40
|
+
new_resolver.namespace.should == 'friends'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "with a non-nil @namespace" do
|
46
|
+
before(:each) do
|
47
|
+
@resolver = VkontakteApi::Resolver.new(:namespace => 'friends')
|
48
|
+
VkontakteApi::Resolver.stub(:vk_method_name).and_return('friends.apiMethod')
|
49
|
+
end
|
50
|
+
|
51
|
+
it "calls #vk_method_name with method name and @namespace" do
|
52
|
+
VkontakteApi::Resolver.should_receive(:vk_method_name).with('api_method', 'friends')
|
53
|
+
@resolver.api_method
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with a non-enumerable result" do
|
58
|
+
before(:each) do
|
59
|
+
@resolver = VkontakteApi::Resolver.new
|
60
|
+
|
61
|
+
@type = stub("Type")
|
62
|
+
VkontakteApi::Resolver.stub(:vk_method_name).and_return([:method_name, @type])
|
63
|
+
|
64
|
+
@typecasted_value = stub("Typecasted value")
|
65
|
+
@resolver.stub(:typecast).and_return(@typecasted_value)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "returns #typecast-ed value" do
|
69
|
+
@resolver.should_receive(:typecast).with(@result, @type).and_return(@typecasted_value)
|
70
|
+
@resolver.method_name.should == @typecasted_value
|
71
|
+
end
|
72
|
+
|
73
|
+
context "when block_given?" do
|
74
|
+
it "yields the #typecast-ed value and returns the result of the block" do
|
75
|
+
block_result = stub("Block result")
|
76
|
+
@typecasted_value.should_receive(:result_method).and_return(block_result)
|
77
|
+
|
78
|
+
@resolver.api_method do |result|
|
79
|
+
result.result_method
|
80
|
+
end.should == block_result
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "with an enumerable result" do
|
86
|
+
before(:each) do
|
87
|
+
@resolver = VkontakteApi::Resolver.new
|
88
|
+
|
89
|
+
@element1 = stub("First element")
|
90
|
+
@element2 = stub("Second element")
|
91
|
+
@enumerable_result = [@element1, @element2]
|
92
|
+
VkontakteApi::API.stub(:call).and_return(@enumerable_result)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "returns the untouched value" do
|
96
|
+
@resolver.method_name.should == @enumerable_result
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when block_given?" do
|
100
|
+
it "yields each element untouched to the block" do
|
101
|
+
result1 = stub("First element after result_method")
|
102
|
+
result2 = stub("Second element after result_method")
|
103
|
+
@element1.should_receive(:result_method).and_return(result1)
|
104
|
+
@element2.should_receive(:result_method).and_return(result2)
|
105
|
+
|
106
|
+
@resolver.api_method do |result|
|
107
|
+
result.result_method
|
108
|
+
end.should == [result1, result2]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe ".vk_method_name" do
|
115
|
+
context "with a usual method name" do
|
116
|
+
context "without a namespace" do
|
117
|
+
it "returns 'methodName'" do
|
118
|
+
VkontakteApi::Resolver.vk_method_name(:api_method).first.should == 'apiMethod'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "with a namespace" do
|
123
|
+
it "returns 'namespace.methodName'" do
|
124
|
+
VkontakteApi::Resolver.vk_method_name(:api_method, 'namespace').first.should == 'namespace.apiMethod'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "returns :anything as a type" do
|
129
|
+
VkontakteApi::Resolver.vk_method_name(:api_method).last.should == :anything
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "with a predicate method name" do
|
134
|
+
it "returns method name without '?'" do
|
135
|
+
VkontakteApi::Resolver.vk_method_name(:is_it_working?).first.should == 'isItWorking'
|
136
|
+
end
|
137
|
+
|
138
|
+
it "returns :boolean as a type" do
|
139
|
+
VkontakteApi::Resolver.vk_method_name(:is_it_working?).last.should == :boolean
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "#typecast" do
|
145
|
+
before(:each) do
|
146
|
+
@resolver = VkontakteApi::Resolver.new
|
147
|
+
end
|
148
|
+
|
149
|
+
context "with an :anything type" do
|
150
|
+
it "returns it's argument untouched" do
|
151
|
+
@resolver.send(:typecast, :some_arg, :anything).should == :some_arg
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "with a :boolean type" do
|
156
|
+
context "and zero result" do
|
157
|
+
it "returns false" do
|
158
|
+
@resolver.send(:typecast, '0', :boolean).should == false
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "and non-zero parameter" do
|
163
|
+
it "returns true" do
|
164
|
+
@resolver.send(:typecast, '1', :boolean).should == true
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VkontakteApi do
|
4
|
+
describe ".configure" do
|
5
|
+
VkontakteApi::Configuration::OPTION_NAMES.each do |name|
|
6
|
+
it "should set the #{name}" do
|
7
|
+
VkontakteApi.configure do |config|
|
8
|
+
config.send("#{name}=", name)
|
9
|
+
VkontakteApi.send(name).should == name
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$: << File.expand_path('../lib', __FILE__)
|
3
|
+
require 'vkontakte_api/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'vkontakte_api'
|
7
|
+
s.version = VkontakteApi::VERSION
|
8
|
+
s.authors = ['Vsevolod Romashov']
|
9
|
+
s.email = ['7@7vn.ru']
|
10
|
+
s.homepage = ''
|
11
|
+
s.summary = %q{Ruby-way wrapper for VKontakte API}
|
12
|
+
s.description = %q{A transparent wrapper for API of vk.com social network called VKontakte. Supports ruby-way method naming (without any method lists inside), result typecasting and any faraday-supported http adapter of your choice (no hardcoded Net::HTTP).}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
|
19
|
+
s.add_runtime_dependency 'activesupport', '~> 3.0'
|
20
|
+
s.add_runtime_dependency 'i18n', '~> 0.6'
|
21
|
+
s.add_runtime_dependency 'faraday', '~> 0.7.6'
|
22
|
+
s.add_runtime_dependency 'yajl-ruby', '~> 1.0'
|
23
|
+
|
24
|
+
s.add_development_dependency 'rake'
|
25
|
+
s.add_development_dependency 'rspec'
|
26
|
+
s.add_development_dependency 'pry'
|
27
|
+
s.add_development_dependency 'awesome_print'
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vkontakte_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Vsevolod Romashov
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &70258037639260 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70258037639260
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: i18n
|
27
|
+
requirement: &70258037638480 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.6'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70258037638480
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: faraday
|
38
|
+
requirement: &70258037637640 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.7.6
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70258037637640
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: yajl-ruby
|
49
|
+
requirement: &70258037636920 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70258037636920
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rake
|
60
|
+
requirement: &70258037656820 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70258037656820
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: &70258037656180 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70258037656180
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: pry
|
82
|
+
requirement: &70258037655480 !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: *70258037655480
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: awesome_print
|
93
|
+
requirement: &70258037654980 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70258037654980
|
102
|
+
description: A transparent wrapper for API of vk.com social network called VKontakte.
|
103
|
+
Supports ruby-way method naming (without any method lists inside), result typecasting
|
104
|
+
and any faraday-supported http adapter of your choice (no hardcoded Net::HTTP).
|
105
|
+
email:
|
106
|
+
- 7@7vn.ru
|
107
|
+
executables: []
|
108
|
+
extensions: []
|
109
|
+
extra_rdoc_files: []
|
110
|
+
files:
|
111
|
+
- .gitignore
|
112
|
+
- Gemfile
|
113
|
+
- MIT-LICENSE
|
114
|
+
- README.md
|
115
|
+
- README.ru.md
|
116
|
+
- Rakefile
|
117
|
+
- lib/vkontakte_api.rb
|
118
|
+
- lib/vkontakte_api/api.rb
|
119
|
+
- lib/vkontakte_api/client.rb
|
120
|
+
- lib/vkontakte_api/configuration.rb
|
121
|
+
- lib/vkontakte_api/error.rb
|
122
|
+
- lib/vkontakte_api/namespaces.yml
|
123
|
+
- lib/vkontakte_api/resolver.rb
|
124
|
+
- lib/vkontakte_api/version.rb
|
125
|
+
- spec/spec_helper.rb
|
126
|
+
- spec/vkontakte_api/api_spec.rb
|
127
|
+
- spec/vkontakte_api/client_spec.rb
|
128
|
+
- spec/vkontakte_api/configuration_spec.rb
|
129
|
+
- spec/vkontakte_api/error_spec.rb
|
130
|
+
- spec/vkontakte_api/resolver_spec.rb
|
131
|
+
- spec/vkontakte_api_spec.rb
|
132
|
+
- vkontakte_api.gemspec
|
133
|
+
homepage: ''
|
134
|
+
licenses: []
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
none: false
|
141
|
+
requirements:
|
142
|
+
- - ! '>='
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
segments:
|
146
|
+
- 0
|
147
|
+
hash: -2826215231838222847
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
+
none: false
|
150
|
+
requirements:
|
151
|
+
- - ! '>='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
segments:
|
155
|
+
- 0
|
156
|
+
hash: -2826215231838222847
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 1.8.10
|
160
|
+
signing_key:
|
161
|
+
specification_version: 3
|
162
|
+
summary: Ruby-way wrapper for VKontakte API
|
163
|
+
test_files:
|
164
|
+
- spec/spec_helper.rb
|
165
|
+
- spec/vkontakte_api/api_spec.rb
|
166
|
+
- spec/vkontakte_api/client_spec.rb
|
167
|
+
- spec/vkontakte_api/configuration_spec.rb
|
168
|
+
- spec/vkontakte_api/error_spec.rb
|
169
|
+
- spec/vkontakte_api/resolver_spec.rb
|
170
|
+
- spec/vkontakte_api_spec.rb
|