vkontakte_api 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/.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
|