vkontakte_api 1.2 → 1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d37878c023a9ef41c525a2e80d94a1116bf7cdf4
4
- data.tar.gz: d6bee0ae8a1dfa7a74d74e26327f5cf880214e9b
3
+ metadata.gz: 60dffad7bbac6d779ff73eaeb39221648bd06b81
4
+ data.tar.gz: c702f943689840e842d49859f2bcc87b10fce869
5
5
  SHA512:
6
- metadata.gz: 100e3698409e4c1c76ac1adbbb75609675b92c965905e5218b32cc5f1dae49d0f69783db01bb7ca5729e724bae8e4718e0f3ffc7cb8ec8cc86a87a7e0d399301
7
- data.tar.gz: 43b9a423fd114d904b395f34fdf510eb72a48657722b2a88c2e15f82bdb8544b6aa2180fe8eb225a3e28aec20b12bbf3bc31cabb788f1f34739f62457d7ada19
6
+ metadata.gz: fc49252ddc7b95434e0f2f5ac59cb4ea4f749c1a30a7026b1bbefa5f570ae836f3b25125f70c9f8026aee2322b5cd4f878e19d90bc9a90f26948951f250d14b8
7
+ data.tar.gz: 90a2c6d2da5ac5e7e08851575373c7bc5e53684a88d5111e7a128026d3aa2accfb8b5c41bd2bedc373b3759009cf35d68c1132eb2f55691da93f37438fc9a1b0
data/.gitignore CHANGED
@@ -2,5 +2,6 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ tmp/*
5
6
  .yardoc/*
6
7
  spec/support/credentials.yml
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 1.3 (01.11.2013)
2
+
3
+ * Корректная работа API-методов `*.search` (спасибо [leonko](https://github.com/leonko))
4
+ * Поддержка IO-объектов в методе `upload` (спасибо [undr](https://github.com/undr))
5
+
1
6
  ## 1.2 (14.07.2013)
2
7
 
3
8
  * Повтор запроса при определенных ошибках
data/Guardfile CHANGED
@@ -1,7 +1,9 @@
1
- guard 'rspec' do
1
+ guard 'rspec', all_on_start: true, all_after_pass: true do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
3
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
4
  watch('spec/spec_helper.rb') { 'spec' }
5
+
6
+ watch('spec/support/mechanized_authorization.rb') { 'spec/integration_spec.rb' }
5
7
  end
6
8
 
7
9
  notification :terminal_notifier, activate: 'com.googlecode.iTerm2'
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ``` ruby
8
8
  # Gemfile
9
- gem 'vkontakte_api', '~> 1.2'
9
+ gem 'vkontakte_api', '~> 1.3'
10
10
  ```
11
11
 
12
12
  или просто
@@ -47,7 +47,7 @@ users.first.last_name # => "Дуров"
47
47
  # то блок будет выполнен для каждого элемента,
48
48
  # и метод вернет обработанный массив
49
49
  fields = [:first_name, :last_name, :screen_name]
50
- @vk.friends.get(fields: fields) do |friend|
50
+ @vk.friends.get(uid: 2, fields: fields) do |friend|
51
51
  "#{friend.first_name} '#{friend.screen_name}' #{friend.last_name}"
52
52
  end
53
53
  # => ["Павел 'durov' Дуров"]
@@ -64,6 +64,13 @@ url = 'http://cs303110.vkontakte.ru/upload.php?act=do_add'
64
64
  VkontakteApi.upload(url: url, photo: ['/path/to/file.jpg', 'image/jpeg'])
65
65
  ```
66
66
 
67
+ Если загружаемый файл доступен как открытый IO-объект, его можно передать альтернативным синтаксисом - IO-объект, MIME-тип и путь к файлу:
68
+
69
+ ``` ruby
70
+ url = 'http://cs303110.vkontakte.ru/upload.php?act=do_add'
71
+ VkontakteApi.upload(url: url, photo: [file_io, 'image/jpeg', '/path/to/file.jpg'])
72
+ ```
73
+
67
74
  Метод вернет ответ сервера ВКонтакте, преобразованный в `Hashie::Mash`; его можно использовать при вызове метода API на последнем этапе процесса загрузки.
68
75
 
69
76
  ### Авторизация
@@ -262,7 +269,6 @@ $ rails generate vkontakte_api:install
262
269
 
263
270
  ## Roadmap
264
271
 
265
- * настраиваемый retry запроса при стандартных исключениях
266
272
  * CLI-интерфейс с автоматической авторизацией
267
273
 
268
274
  ## Участие в разработке
@@ -69,6 +69,16 @@ module VkontakteApi
69
69
  end.keys
70
70
  end
71
71
 
72
+ # If the called method is a namespace, it creates and returns a new `VkontakteApi::Namespace` instance.
73
+ # Otherwise it creates a `VkontakteApi::Method` instance and calls it passing the arguments and a block.
74
+ def method_missing(*args, &block)
75
+ if Namespace.exists?(args.first)
76
+ create_namespace(args.first)
77
+ else
78
+ call_method(args, &block)
79
+ end
80
+ end
81
+
72
82
  private
73
83
  def settings
74
84
  @settings ||= self.get_user_settings
@@ -1,7 +1,36 @@
1
1
  module VkontakteApi
2
- # An API method namespace (such as `users` or `friends`). It just includes `Resolvable` and `Resolver`.
2
+ # An API method namespace (such as `users` or `friends`).
3
+ #
4
+ # It includes `Resolvable` and `Resolver` and calls API methods via `Resolver#call_method`.
5
+ # It also holds the list of all known namespaces.
3
6
  class Namespace
4
7
  include Resolvable
5
8
  include Resolver
9
+
10
+ # Creates and calls the `VkontakteApi::Method` using `VkontakteApi::Resolver#call_method`.
11
+ def method_missing(*args, &block)
12
+ call_method(args, &block)
13
+ end
14
+
15
+ class << self
16
+ # An array of all method namespaces.
17
+ #
18
+ # Lazily loads the list from `namespaces.yml` and caches it.
19
+ # @return [Array] An array of strings
20
+ def names
21
+ if @names.nil?
22
+ filename = File.expand_path('../namespaces.yml', __FILE__)
23
+ @names = YAML.load_file(filename)
24
+ end
25
+
26
+ @names
27
+ end
28
+
29
+ # Does a given namespace exist?
30
+ # @param [String, Symbol] name
31
+ def exists?(name)
32
+ names.include?(name.to_s)
33
+ end
34
+ end
6
35
  end
7
36
  end
@@ -7,7 +7,7 @@ module VkontakteApi
7
7
  # @param [String] name The name of this resolvable.
8
8
  # @option options [Hashie::Mash] :resolver A mash holding information about the previous resolver.
9
9
  def initialize(name, options = {})
10
- @name = name
10
+ @name = name.to_s
11
11
  @previous_resolver = options.delete(:resolver)
12
12
  end
13
13
 
@@ -1,41 +1,26 @@
1
1
  module VkontakteApi
2
2
  # A mixin for classes that will resolve other classes' objects via `#method_missing`.
3
3
  module Resolver
4
- # Main methods dispatch.
5
- #
6
- # If the called method is a namespace, it creates and returns a new `VkontakteApi::Namespace` instance.
7
- # Otherwise it creates a `VkontakteApi::Method` instance and invokes it's `#call` method passing it the arguments and a block.
8
- def method_missing(method_name, *args, &block)
9
- method_name = method_name.to_s
10
-
11
- if Resolver.namespaces.include?(method_name)
12
- # called from Client
13
- Namespace.new(method_name, resolver: resolver)
14
- else
15
- # called from Namespace or one-level method
16
- Method.new(method_name, resolver: resolver).call(args.first || {}, &block)
17
- end
18
- end
19
-
20
4
  # A `Hashie::Mash` structure holding the name and token of current instance.
21
5
  # @return [Hashie::Mash]
22
6
  def resolver
23
7
  @resolver ||= Hashie::Mash.new(name: @name, token: token)
24
8
  end
25
9
 
10
+ private
11
+ def create_namespace(name)
12
+ Namespace.new(name, resolver: resolver)
13
+ end
14
+
15
+ def create_method(name)
16
+ Method.new(name, resolver: resolver)
17
+ end
18
+
19
+ def call_method(args, &block)
20
+ create_method(args.shift).call(args.first || {}, &block)
21
+ end
22
+
26
23
  class << self
27
- # An array of method namespaces.
28
- # Lazily loads the list from `namespaces.yml` and caches it.
29
- # @return [Array]
30
- def namespaces
31
- if @namespaces.nil?
32
- filename = File.expand_path('../namespaces.yml', __FILE__)
33
- @namespaces = YAML.load_file(filename)
34
- end
35
-
36
- @namespaces
37
- end
38
-
39
24
  # When this module is included, it undefines the `:send` instance method in the `base_class`
40
25
  # so it can be resolved via `method_missing`.
41
26
  def included(base_class)
@@ -12,15 +12,15 @@ module VkontakteApi
12
12
  # VkontakteApi.upload(
13
13
  # url: 'http://example.com/upload',
14
14
  # file1: ['/path/to/file1.jpg', 'image/jpeg'],
15
- # file2: ['/path/to/file2.png', 'image/png']
15
+ # file2: [io_object, 'image/png', '/path/to/file2.png']
16
16
  # )
17
17
  def upload(params = {})
18
18
  url = params.delete(:url)
19
19
  raise ArgumentError, 'You should pass :url parameter' unless url
20
20
 
21
21
  files = {}
22
- params.each do |param_name, (file_path, file_type)|
23
- files[param_name] = Faraday::UploadIO.new(file_path, file_type)
22
+ params.each do |param_name, (file_path_or_io, file_type, file_path)|
23
+ files[param_name] = Faraday::UploadIO.new(file_path_or_io, file_type, file_path)
24
24
  end
25
25
 
26
26
  API.connection.post(url, files).body
@@ -1,4 +1,4 @@
1
1
  module VkontakteApi
2
2
  # Library version.
3
- VERSION = '1.2'
3
+ VERSION = '1.3'
4
4
  end
@@ -13,70 +13,67 @@ describe "Integration" do
13
13
  end
14
14
 
15
15
  describe "unauthorized requests" do
16
- before(:each) do
17
- @vk = VK::Client.new
18
- end
16
+ let(:vk) { VK::Client.new }
19
17
 
20
18
  it "get users" do
21
- user = @vk.users.get(uid: 1).first
22
- user.uid.should == 1
23
- user.last_name.should_not be_empty
24
- user.first_name.should_not be_empty
19
+ user = vk.users.get(uid: 1).first
20
+ expect(user.uid).to eq(1)
21
+ expect(user.last_name).not_to be_empty
22
+ expect(user.first_name).not_to be_empty
23
+ end
24
+
25
+ it "search newsfeed" do
26
+ news = vk.newsfeed.search(q: 'vk', count: 1)
27
+ expect(news).to be_a(Enumerable)
25
28
  end
26
29
  end
27
30
 
28
31
  if MechanizedAuthorization.on?
29
32
  describe "authorized requests" do
30
- before(:each) do
31
- @vk = MechanizedAuthorization.client
32
- end
33
+ let(:vk) { MechanizedAuthorization.client }
33
34
 
34
35
  it "get groups" do
35
- groups = @vk.groups.get
36
- groups.should include(1)
36
+ pending 'MechanizedAuthorization not working'
37
+ expect(vk.groups.get).to include(1)
37
38
  end
38
39
  end
39
40
 
40
41
  describe "requests with camelCase and predicate methods" do
41
- before(:each) do
42
- @vk = MechanizedAuthorization.client
43
- end
42
+ let(:vk) { MechanizedAuthorization.client }
44
43
 
45
44
  it "convert method names to vk.com format" do
46
- @vk.is_app_user?.should be_true
45
+ pending 'MechanizedAuthorization not working'
46
+ expect(vk.is_app_user?).to be_true
47
47
  end
48
48
  end
49
49
  end
50
50
 
51
51
  describe "requests with array arguments" do
52
- before(:each) do
53
- @vk = VK::Client.new
54
- end
52
+ let(:vk) { VK::Client.new }
55
53
 
56
54
  it "join arrays with a comma" do
57
- users = @vk.users.get(uids: [1, 2, 3], fields: %w[first_name last_name screen_name])
58
- users.first.screen_name.should_not be_empty
55
+ users = vk.users.get(uids: [1, 2, 3], fields: %w[first_name last_name screen_name])
56
+ expect(users.first.screen_name).not_to be_empty
59
57
  end
60
58
  end
61
59
 
62
60
  describe "requests with blocks" do
63
- before(:each) do
64
- @vk = VK::Client.new
65
- end
61
+ let(:vk) { VK::Client.new }
66
62
 
67
63
  it "map the result with a block" do
68
- users = @vk.users.get(uid: 1) do |user|
64
+ users = vk.users.get(uid: 1) do |user|
69
65
  "#{user.last_name} #{user.first_name}"
70
66
  end
71
67
 
72
- users.first.should_not be_empty
68
+ expect(users.first).not_to be_empty
73
69
  end
74
70
  end
75
71
 
76
72
  describe "authorization" do
77
73
  context "with a scope" do
78
74
  it "returns a correct url" do
79
- VK.authorization_url(scope: %w[friends groups]).should include('scope=friends%2Cgroups')
75
+ url = VK.authorization_url(scope: %w[friends groups])
76
+ expect(url).to include('scope=friends%2Cgroups')
80
77
  end
81
78
  end
82
79
  end
@@ -23,13 +23,13 @@ describe VkontakteApi::API do
23
23
 
24
24
  context "called with a token parameter" do
25
25
  it "sends it to .connection" do
26
- subject.should_receive(:connection).with(url: VkontakteApi::API::URL_PREFIX, token: 'token')
26
+ expect(subject).to receive(:connection).with(url: VkontakteApi::API::URL_PREFIX, token: 'token')
27
27
  subject.call('apiMethod', { some: :params }, 'token')
28
28
  end
29
29
  end
30
30
 
31
31
  it "returns the response body" do
32
- subject.call('apiMethod').should == @result
32
+ expect(subject.call('apiMethod')).to eq(@result)
33
33
  end
34
34
 
35
35
  it "uses an HTTP verb from VkontakteApi.http_verb" do
@@ -37,7 +37,7 @@ describe VkontakteApi::API do
37
37
  VkontakteApi.http_verb = http_verb
38
38
 
39
39
  response = double("Response", body: double)
40
- @connection.should_receive(:send).with(http_verb, 'apiMethod', {}).and_return(response)
40
+ expect(@connection).to receive(:send).with(http_verb, 'apiMethod', {}).and_return(response)
41
41
  subject.call('apiMethod')
42
42
  end
43
43
 
@@ -51,27 +51,27 @@ describe VkontakteApi::API do
51
51
  faraday_options = double("Faraday options")
52
52
  VkontakteApi.stub(:faraday_options).and_return(faraday_options)
53
53
  url = double("URL")
54
- Faraday.should_receive(:new).with(url, faraday_options)
55
- connection = subject.connection(url: url)
54
+
55
+ expect(Faraday).to receive(:new).with(url, faraday_options)
56
+ subject.connection(url: url)
56
57
  end
57
58
 
58
59
  context "without a token" do
59
60
  it "creates a connection without an oauth2 middleware" do
60
- connection = subject.connection
61
- connection.builder.handlers.map(&:name).should_not include('FaradayMiddleware::OAuth2')
61
+ handler_names = subject.connection.builder.handlers.map(&:name)
62
+ expect(handler_names).not_to include('FaradayMiddleware::OAuth2')
62
63
  end
63
64
  end
64
65
 
65
66
  context "with a token" do
66
- before(:each) do
67
- @token = double("Token")
68
- end
67
+ let(:token) { double("Token") }
69
68
 
70
69
  it "creates a connection with an oauth2 middleware" do
71
- connection = subject.connection(token: @token)
70
+ connection = subject.connection(token: token)
72
71
  handler = connection.builder.handlers.first
73
- handler.name.should == 'FaradayMiddleware::OAuth2'
74
- handler.instance_variable_get(:@args).should == [@token]
72
+
73
+ expect(handler.name).to eq('FaradayMiddleware::OAuth2')
74
+ expect(handler.instance_variable_get(:@args)).to eq([token])
75
75
  end
76
76
  end
77
77
  end
@@ -18,35 +18,38 @@ describe VkontakteApi::Authorization do
18
18
 
19
19
  @client = double("OAuth2::Client instance", auth_code: @auth_code, implicit: @implicit, client_credentials: @client_credentials)
20
20
  OAuth2::Client.stub(:new).and_return(@client)
21
-
22
- @auth = Object.new
23
- @auth.extend VkontakteApi::Authorization
24
21
  end
25
22
 
23
+ let(:auth) do
24
+ Object.new.tap do |object|
25
+ object.extend VkontakteApi::Authorization
26
+ end
27
+ end
28
+
26
29
  describe "#authorization_url" do
27
30
  before(:each) do
28
- @auth.stub(:client).and_return(@client)
31
+ auth.stub(:client).and_return(@client)
29
32
  end
30
33
 
31
34
  context "with a site type" do
32
35
  it "returns a valid authorization url" do
33
- @auth_code.should_receive(:authorize_url).with(redirect_uri: @redirect_uri)
34
- @auth.authorization_url(type: :site).should == @url
36
+ expect(@auth_code).to receive(:authorize_url).with(redirect_uri: @redirect_uri)
37
+ expect(auth.authorization_url(type: :site)).to eq(@url)
35
38
  end
36
39
  end
37
40
 
38
41
  context "with a client type" do
39
42
  it "returns a valid authorization url" do
40
- @implicit.should_receive(:authorize_url).with(redirect_uri: @redirect_uri)
41
- @auth.authorization_url(type: :client).should == @url
43
+ expect(@implicit).to receive(:authorize_url).with(redirect_uri: @redirect_uri)
44
+ expect(auth.authorization_url(type: :client)).to eq(@url)
42
45
  end
43
46
  end
44
47
 
45
48
  context "given a redirect_uri" do
46
49
  it "prefers the given uri over VkontakteApi.redirect_uri" do
47
50
  redirect_uri = 'http://example.com/oauth/callback'
48
- @auth_code.should_receive(:authorize_url).with(redirect_uri: redirect_uri)
49
- @auth.authorization_url(redirect_uri: redirect_uri)
51
+ expect(@auth_code).to receive(:authorize_url).with(redirect_uri: redirect_uri)
52
+ auth.authorization_url(redirect_uri: redirect_uri)
50
53
  end
51
54
  end
52
55
 
@@ -55,9 +58,9 @@ describe VkontakteApi::Authorization do
55
58
  scope = double("Scope")
56
59
  flat_scope = double("Flat scope")
57
60
 
58
- VkontakteApi::Utils.should_receive(:flatten_argument).with(scope).and_return(flat_scope)
59
- @auth_code.should_receive(:authorize_url).with(redirect_uri: @redirect_uri, scope: flat_scope)
60
- @auth.authorization_url(scope: scope)
61
+ expect(VkontakteApi::Utils).to receive(:flatten_argument).with(scope).and_return(flat_scope)
62
+ expect(@auth_code).to receive(:authorize_url).with(redirect_uri: @redirect_uri, scope: flat_scope)
63
+ auth.authorization_url(scope: scope)
61
64
  end
62
65
  end
63
66
  end
@@ -70,42 +73,42 @@ describe VkontakteApi::Authorization do
70
73
  end
71
74
 
72
75
  it "gets the token" do
73
- @auth_code.should_receive(:get_token).with(@code, redirect_uri: @redirect_uri)
74
- @auth.authorize(type: :site, code: @code)
76
+ expect(@auth_code).to receive(:get_token).with(@code, redirect_uri: @redirect_uri)
77
+ auth.authorize(type: :site, code: @code)
75
78
  end
76
79
  end
77
80
 
78
81
  context "with an app_server type" do
79
82
  it "gets the token" do
80
- @client_credentials.should_receive(:get_token).with({ redirect_uri: @redirect_uri }, subject::OPTIONS[:client_credentials])
81
- @auth.authorize(type: :app_server)
83
+ expect(@client_credentials).to receive(:get_token).with({ redirect_uri: @redirect_uri }, subject::OPTIONS[:client_credentials])
84
+ auth.authorize(type: :app_server)
82
85
  end
83
86
  end
84
87
 
85
88
  context "with an unknown type" do
86
89
  it "raises an ArgumentError" do
87
90
  expect {
88
- @auth.authorize(type: :unknown)
91
+ auth.authorize(type: :unknown)
89
92
  }.to raise_error(ArgumentError)
90
93
  end
91
94
  end
92
95
 
93
96
  it "builds a VkontakteApi::Client instance with the received token" do
94
97
  client = double("VkontakteApi::Client instance")
95
- VkontakteApi::Client.should_receive(:new).with(@token).and_return(client)
96
- @auth.authorize.should == client
98
+ expect(VkontakteApi::Client).to receive(:new).with(@token).and_return(client)
99
+ expect(auth.authorize).to eq(client)
97
100
  end
98
101
  end
99
102
 
100
103
  describe "#client" do
101
104
  it "creates and returns an OAuth2::Client instance" do
102
- OAuth2::Client.should_receive(:new).with(@app_id, @app_secret, subject::OPTIONS[:client])
103
- @auth.send(:client).should == @client
105
+ expect(OAuth2::Client).to receive(:new).with(@app_id, @app_secret, subject::OPTIONS[:client])
106
+ expect(auth.send(:client)).to eq(@client)
104
107
  end
105
108
 
106
109
  it "caches the result" do
107
- OAuth2::Client.should_receive(:new).once
108
- 5.times { @auth.send(:client) }
110
+ expect(OAuth2::Client).to receive(:new).once
111
+ 5.times { auth.send(:client) }
109
112
  end
110
113
  end
111
114
  end