dribbble 0.0.4 → 1.0.0.beta1

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -1
  3. data/Guardfile +0 -5
  4. data/dribbble.gemspec +0 -3
  5. data/lib/dribbble/attachment.rb +7 -0
  6. data/lib/dribbble/base.rb +64 -5
  7. data/lib/dribbble/bucket.rb +31 -0
  8. data/lib/dribbble/client.rb +0 -7
  9. data/lib/dribbble/comment.rb +4 -0
  10. data/lib/dribbble/like.rb +7 -0
  11. data/lib/dribbble/project.rb +11 -0
  12. data/lib/dribbble/shot.rb +62 -0
  13. data/lib/dribbble/team.rb +4 -0
  14. data/lib/dribbble/user.rb +47 -6
  15. data/lib/dribbble/utils/creatable.rb +33 -0
  16. data/lib/dribbble/utils/deletable.rb +21 -0
  17. data/lib/dribbble/utils/findable.rb +17 -0
  18. data/lib/dribbble/utils/has_children.rb +33 -0
  19. data/lib/dribbble/utils/updatable.rb +24 -0
  20. data/lib/dribbble/utils.rb +38 -7
  21. data/lib/dribbble/version.rb +1 -1
  22. data/spec/lib/dribbble/base_spec.rb +161 -4
  23. data/spec/lib/dribbble/bucket_spec.rb +136 -0
  24. data/spec/lib/dribbble/client_spec.rb +2 -23
  25. data/spec/lib/dribbble/project_spec.rb +45 -0
  26. data/spec/lib/dribbble/shot_spec.rb +254 -0
  27. data/spec/lib/dribbble/user_spec.rb +173 -23
  28. data/spec/spec_helper.rb +14 -17
  29. data/spec/support/dribbble.rb +159 -20
  30. data/spec/support/fixtures/attachment_success.json +9 -0
  31. data/spec/support/fixtures/attachments_success.json +11 -0
  32. data/spec/support/fixtures/bucket_created.json +8 -0
  33. data/spec/support/fixtures/bucket_success.json +8 -0
  34. data/spec/support/fixtures/bucket_updated.json +8 -0
  35. data/spec/support/fixtures/comments_success.json +37 -0
  36. data/spec/support/fixtures/current_user_success.json +25 -0
  37. data/spec/support/fixtures/followers_success.json +33 -0
  38. data/spec/support/fixtures/following_success.json +33 -0
  39. data/spec/support/fixtures/project_success.json +8 -0
  40. data/spec/support/fixtures/projects_success.json +10 -0
  41. data/spec/support/fixtures/shot_likes_success.json +33 -0
  42. data/spec/support/fixtures/shot_success.json +85 -0
  43. data/spec/support/fixtures/shot_updated.json +85 -0
  44. data/spec/support/fixtures/teams_success.json +28 -0
  45. data/spec/support/fixtures/user_likes_success.json +91 -0
  46. metadata +52 -48
  47. data/spec/factories.rb +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8400bf96dbeff8189c81818af04e896294594bce
4
- data.tar.gz: 145e740eeebc9befa53683f0dc5babf0f04fee40
3
+ metadata.gz: 85bba0d85d30e2dc9d204fc5200702db45886d01
4
+ data.tar.gz: e9c6c9ed96e02be262937fde7bd386f34f829969
5
5
  SHA512:
6
- metadata.gz: 02f7f12716c85c4c24b30fedec8c4284ea4b7f0fa03b0afa2b27a6b76e42f4a047112993eff269cde7efbbf4b3ceeb6932a979de57bdc594658fa34fa0782a13
7
- data.tar.gz: c07409463d7f33321a21e5a2e9896f61e6e18ce86172cc44bc60ed4ea5cb0f7f4c57ba4425a5820229835dcaf492018e65efb9046e33d01fd3d2058e5aeba587
6
+ metadata.gz: 2aca53d14455683154a1f0cd2c34110e44fe4e6ab3cb88d3fd587992ead681107e957e5c99747e207ea3e8273f2a1c6174551cc5fbb995aa45a9a382e8483443
7
+ data.tar.gz: 73e565e06a9d4d4947b955175ded0eb7651ceca7a4b5c6eff65120298dedae9098cc36ae80322d36b2cdf1430adeda6e99ec0a80e70c8c00f11532b9b31c68a0
data/.travis.yml CHANGED
@@ -4,4 +4,10 @@ cache: bundler
4
4
  rvm:
5
5
  - 2.0.0
6
6
  - 2.1.0
7
- - 2.1.3
7
+ - 2.1.5
8
+ - 2.2.0-preview2
9
+
10
+ matrix:
11
+ fast_finish: true
12
+ allow_failures:
13
+ - rvm: 2.2.0-preview2
data/Guardfile CHANGED
@@ -1,8 +1,3 @@
1
- guard 'spork', rspec_env: { 'RAILS_ENV' => 'test' } do
2
- watch('Gemfile.lock')
3
- watch('spec/spec_helper.rb') { :rspec }
4
- end
5
-
6
1
  guard :rspec, cmd: 'bundle exec rspec' do
7
2
  watch(/^spec\/.+_spec\.rb$/)
8
3
  watch(/^lib\/(.+)\.rb$/) { |m| "spec/lib/#{m[1]}_spec.rb" }
data/dribbble.gemspec CHANGED
@@ -20,9 +20,6 @@ Gem::Specification.new do |s|
20
20
  s.add_development_dependency 'rake', '~> 10.3'
21
21
  s.add_development_dependency 'rspec', '~> 2.14'
22
22
  s.add_development_dependency 'guard-rspec', '~> 4.3'
23
- s.add_development_dependency 'guard-spork', '~> 1.5'
24
23
  s.add_development_dependency 'sinatra', '~> 1.4'
25
24
  s.add_development_dependency 'webmock', '~> 1.17'
26
- s.add_development_dependency 'factory_girl', '~> 4.0'
27
- s.add_development_dependency 'faker', '~> 1.3'
28
25
  end
@@ -0,0 +1,7 @@
1
+ module Dribbble
2
+ class Attachment < Dribbble::Base
3
+ def self.available_fields
4
+ %i(file)
5
+ end
6
+ end
7
+ end
data/lib/dribbble/base.rb CHANGED
@@ -1,10 +1,13 @@
1
1
  require 'dribbble/utils'
2
+ require 'dribbble/utils/has_children'
2
3
 
3
4
  module Dribbble
4
5
  class Base
5
6
  include Dribbble::Utils
6
7
  extend Dribbble::Utils
7
8
 
9
+ include Dribbble::Utils::HasChildren
10
+
8
11
  attr_reader :token
9
12
 
10
13
  def initialize(token, json)
@@ -12,22 +15,78 @@ module Dribbble
12
15
  @raw = json.is_a?(Hash) ? json : JSON.parse(json)
13
16
 
14
17
  @raw.each do |k, v|
15
- define_singleton_method(k) { v }
18
+ define_singleton_method(k) { @raw[k] } unless self.respond_to?(k)
16
19
  end
17
20
  end
18
21
 
19
- def self.batch_new(token, json)
22
+ def self.batch_new(token, json, kind = nil)
20
23
  json = JSON.parse json unless json.is_a? Hash
21
24
  json.map do |obj|
22
- new token, obj
25
+ if kind
26
+ new token, obj[kind]
27
+ else
28
+ new token, obj
29
+ end
23
30
  end
24
31
  end
25
32
 
33
+ # Get a single bucket
34
+ def get_bucket(id)
35
+ Dribbble::Bucket.new @token, html_get("/buckets/#{id}")
36
+ end
37
+
38
+ # Get authenticated user's buckets
39
+ def get_buckets(attrs = {})
40
+ Dribbble::Bucket.batch_new token, html_get('/user/buckets', attrs)
41
+ end
42
+
43
+ # Get authenticated user's followers
44
+ def get_followers(attrs = {})
45
+ Dribbble::User.batch_new token, html_get('/user/followers', attrs)
46
+ end
47
+
48
+ # Get authenticated user's likes
49
+ def get_likes(attrs = {})
50
+ Dribbble::Shot.batch_new token, html_get('/user/likes', attrs), 'shot'
51
+ end
52
+
53
+ # Get a single project
54
+ def get_project(id)
55
+ Dribbble::Project.new @token, html_get("/projects/#{id}")
56
+ end
57
+
58
+ # Get authenticated user's followers
59
+ def get_projects(attrs = {})
60
+ Dribbble::Project.batch_new token, html_get('/user/projects', attrs)
61
+ end
62
+
63
+ # Get a single Shot
64
+ def get_shot(id)
65
+ Dribbble::Shot.new @token, html_get("/shots/#{id}")
66
+ end
67
+
68
+ # Get authenticated user's shots
69
+ def get_shots(attrs = {})
70
+ Dribbble::Shot.batch_new token, html_get('/user/shots', attrs)
71
+ end
72
+
73
+ # Get authenticated user's followees shots
74
+ # Limited to first 600 shots regardless of the pagination
75
+ def get_following_shots(attrs = {})
76
+ Dribbble::Shot.batch_new token, html_get('/user/following/shots', attrs)
77
+ end
78
+
79
+ # Get authenticated user's teams
80
+ def get_teams(attrs = {})
81
+ Dribbble::Team.batch_new token, html_get('/user/teams', attrs)
82
+ end
83
+
84
+ # Get a single User or the authenticated one
26
85
  def get_user(id = nil)
27
86
  if id
28
- Dribbble::User.new @token, get("/users/#{id}")
87
+ Dribbble::User.new @token, html_get("/users/#{id}")
29
88
  else
30
- Dribbble::User.new @token, get('/user')
89
+ Dribbble::User.new @token, html_get('/user')
31
90
  end
32
91
  end
33
92
  end
@@ -1,4 +1,35 @@
1
+ require 'dribbble/utils/findable'
2
+ require 'dribbble/utils/creatable'
3
+ require 'dribbble/utils/updatable'
4
+ require 'dribbble/utils/deletable'
5
+
1
6
  module Dribbble
2
7
  class Bucket < Dribbble::Base
8
+ include Dribbble::Utils::Findable
9
+ include Dribbble::Utils::Creatable
10
+ include Dribbble::Utils::Updatable
11
+ include Dribbble::Utils::Deletable
12
+
13
+ def shots(attrs = {})
14
+ Dribbble::Shot.batch_new token, html_get("/bucket/#{id}/shots", attrs)
15
+ end
16
+
17
+ def add_shot(shot)
18
+ shot_id = shot.is_a?(Dribbble::Shot) ? shot.id : shot
19
+ res = html_put("/buckets/#{id}/shots") do |payload|
20
+ payload[:shot_id] = shot_id
21
+ end
22
+ res.code == 204 ? true : false
23
+ end
24
+
25
+ def remove_shot(shot)
26
+ shot_id = shot.is_a?(Dribbble::Shot) ? shot.id : shot
27
+ res = html_delete "/buckets/#{id}/shots", shot_id: shot_id
28
+ res.code == 204 ? true : false
29
+ end
30
+
31
+ def self.available_fields
32
+ %i(name description)
33
+ end
3
34
  end
4
35
  end
@@ -13,12 +13,5 @@ module Dribbble
13
13
  @token = token
14
14
  fail Dribbble::Error::MissingToken if @token.nil?
15
15
  end
16
-
17
- def create_shot(attrs = {})
18
- fields = %i(title image description tags team_id rebound_source_id)
19
- post '/shots' do |payload|
20
- fields.each { |f| payload[f] = attrs[f] }
21
- end
22
- end
23
16
  end
24
17
  end
@@ -0,0 +1,4 @@
1
+ module Dribbble
2
+ class Comment < Dribbble::Base
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Dribbble
2
+ class Like < Dribbble::Base
3
+ def user
4
+ @user ||= Dribbble::User.new token, @raw['user']
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ require 'dribbble/utils/findable'
2
+
3
+ module Dribbble
4
+ class Project < Dribbble::Base
5
+ include Dribbble::Utils::Findable
6
+
7
+ def shots(attrs = {})
8
+ Dribbble::Shot.batch_new token, html_get("/projects/#{id}/shots", attrs)
9
+ end
10
+ end
11
+ end
data/lib/dribbble/shot.rb CHANGED
@@ -1,4 +1,66 @@
1
+ require 'dribbble/utils/findable'
2
+ require 'dribbble/utils/creatable'
3
+ require 'dribbble/utils/updatable'
4
+ require 'dribbble/utils/deletable'
5
+ require 'dribbble/attachment'
6
+ require 'dribbble/comment'
7
+ require 'dribbble/like'
8
+
1
9
  module Dribbble
2
10
  class Shot < Dribbble::Base
11
+ include Dribbble::Utils::Findable
12
+ include Dribbble::Utils::Creatable
13
+ include Dribbble::Utils::Updatable
14
+ include Dribbble::Utils::Deletable
15
+
16
+ has_many :attachments, :buckets, :comments, :likes, :projects
17
+ has_many :rebounds, as: Dribbble::Shot
18
+
19
+ def self.all(token, attrs = {})
20
+ @token = token
21
+ batch_new token, html_get('/shots', attrs)
22
+ end
23
+
24
+ def self.available_fields
25
+ %i(title image description tags team_id rebound_source_id)
26
+ end
27
+
28
+ def self.after_create(res)
29
+ res.code == 202 ? res.headers[:location].split('/').last : false
30
+ end
31
+
32
+ def create_attachment(attrs = {})
33
+ res = html_post "/shots/#{id}/attachments" do |payload|
34
+ Dribbble::Attachment.available_fields.each do |field|
35
+ payload[field] = attrs[field]
36
+ end
37
+ end
38
+ res.code == 202 ? true : false
39
+ end
40
+
41
+ def find_attachment(attachment_id)
42
+ Dribbble::Attachment.new token, html_get("/shots/#{id}/attachments/#{attachment_id}")
43
+ end
44
+
45
+ def like?
46
+ html_get "/shots/#{id}/like"
47
+ true
48
+ rescue RestClient::ResourceNotFound
49
+ false
50
+ end
51
+
52
+ def like!
53
+ res = html_post "/shots/#{id}/like"
54
+ res.code == 201 ? true : false
55
+ end
56
+
57
+ def unlike!
58
+ res = html_delete "/shots/#{id}/like"
59
+ res.code == 204 ? true : false
60
+ end
61
+
62
+ def rebounds(attrs = {})
63
+ Dribbble::Shot.batch_new token, html_get("/shots/#{id}/rebounds", attrs)
64
+ end
3
65
  end
4
66
  end
@@ -0,0 +1,4 @@
1
+ module Dribbble
2
+ class Team < Dribbble::Base
3
+ end
4
+ end
data/lib/dribbble/user.rb CHANGED
@@ -1,19 +1,60 @@
1
+ require 'dribbble/utils/findable'
1
2
  require 'dribbble/bucket'
3
+ require 'dribbble/project'
2
4
  require 'dribbble/shot'
5
+ require 'dribbble/team'
3
6
 
4
7
  module Dribbble
5
8
  class User < Dribbble::Base
6
- def self.find(token, id = nil)
7
- @token = token
8
- get_user(id)
9
- end
9
+ include Dribbble::Utils::Findable
10
10
 
11
11
  def buckets(attrs = {})
12
- Dribbble::Bucket.batch_new token, get("/users/#{id}/buckets", attrs)
12
+ Dribbble::Bucket.batch_new token, html_get("/users/#{id}/buckets", attrs)
13
+ end
14
+
15
+ def followers(attrs = {})
16
+ Dribbble::User.batch_new token, html_get("/users/#{id}/followers", attrs)
17
+ end
18
+
19
+ def following(attrs = {})
20
+ Dribbble::User.batch_new token, html_get("/users/#{id}/following", attrs), 'followee'
21
+ end
22
+
23
+ def following?(other_user_id = nil)
24
+ if other_user_id
25
+ html_get "/users/#{id}/following/#{other_user_id}"
26
+ else
27
+ html_get "/user/following/#{id}"
28
+ end
29
+ true
30
+ rescue RestClient::ResourceNotFound
31
+ false
32
+ end
33
+
34
+ def follow!
35
+ res = html_put "/users/#{id}/follow"
36
+ res.code == 204 ? true : false
37
+ end
38
+
39
+ def unfollow!
40
+ res = html_delete "/users/#{id}/follow"
41
+ res.code == 204 ? true : false
42
+ end
43
+
44
+ def likes(attrs = {})
45
+ Dribbble::Shot.batch_new token, html_get("/users/#{id}/likes", attrs), 'shot'
46
+ end
47
+
48
+ def projects(attrs = {})
49
+ Dribbble::Project.batch_new token, html_get("/users/#{id}/projects", attrs)
13
50
  end
14
51
 
15
52
  def shots(attrs = {})
16
- Dribbble::Shot.batch_new token, get("/users/#{id}/shots", attrs)
53
+ Dribbble::Shot.batch_new token, html_get("/users/#{id}/shots", attrs)
54
+ end
55
+
56
+ def teams(attrs = {})
57
+ Dribbble::Team.batch_new token, html_get("/users/#{id}/teams", attrs)
17
58
  end
18
59
  end
19
60
  end
@@ -0,0 +1,33 @@
1
+ module Dribbble
2
+ module Utils
3
+ module Creatable
4
+ module ClassMethods
5
+ def create(token, attrs)
6
+ @token = token
7
+ res = html_post "/#{api_endpoint}" do |payload|
8
+ available_fields.each { |f| payload[f] = attrs[f] }
9
+ end
10
+ after_create(res)
11
+ end
12
+
13
+ # Need to be override if pluralize isn't that naive
14
+ def api_endpoint
15
+ "#{name.split('::').last.downcase}s"
16
+ end
17
+
18
+ # Need to be redeclared in the model
19
+ def available_fields
20
+ fail "You need to redeclare this methods in your model"
21
+ end
22
+
23
+ def after_create(res)
24
+ new @token, res
25
+ end
26
+ end
27
+
28
+ def self.included(base)
29
+ base.extend(ClassMethods)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ module Dribbble
2
+ module Utils
3
+ module Deletable
4
+ def delete
5
+ res = html_delete "/#{self.class.api_endpoint}/#{id}"
6
+ res.code == 204 ? true : false
7
+ end
8
+
9
+ module ClassMethods
10
+ def delete(token, id)
11
+ object = find token, id
12
+ object.delete
13
+ end
14
+ end
15
+
16
+ def self.included(base)
17
+ base.extend(ClassMethods)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module Dribbble
2
+ module Utils
3
+ module Findable
4
+ module ClassMethods
5
+ def find(token, id)
6
+ @token = token
7
+ @client = Dribbble::Client.new token: @token
8
+ @client.send "get_#{name.split('::').last.downcase}", id
9
+ end
10
+ end
11
+
12
+ def self.included(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ module Dribbble
2
+ module Utils
3
+ module HasChildren
4
+ module ClassMethods
5
+ def has_many(*fields)
6
+ if fields[1].is_a? Hash
7
+ field = fields[0]
8
+ singularized_field = field[0...-1]
9
+ klass = fields[1][:as]
10
+
11
+ define_method field do |attrs = {}|
12
+ klass.batch_new token, html_get("/#{pluralized_class_name}/#{id}/#{klass.pluralized_class_name}", attrs)
13
+ end
14
+ else
15
+ fields.each do |field|
16
+ cheat = field
17
+
18
+ define_method cheat do |attrs = {}|
19
+ singularized_field = cheat[0...-1]
20
+ klass = Object.const_get "Dribbble::#{singularized_field.capitalize}"
21
+ klass.batch_new token, html_get("/#{pluralized_class_name}/#{id}/#{klass.pluralized_class_name}", attrs)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def self.included(base)
29
+ base.extend(ClassMethods)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ module Dribbble
2
+ module Utils
3
+ module Updatable
4
+ def update(attrs)
5
+ res = html_put "/#{self.class.api_endpoint}/#{id}" do |payload|
6
+ self.class.available_fields.each { |f| payload[f] = attrs[f] }
7
+ end
8
+ @raw = JSON.parse res
9
+ self
10
+ end
11
+
12
+ module ClassMethods
13
+ def update(token, id, attrs)
14
+ object = find token, id
15
+ object.update attrs
16
+ end
17
+ end
18
+
19
+ def self.included(base)
20
+ base.extend(ClassMethods)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -7,9 +7,20 @@ module Dribbble
7
7
  per_page: 100
8
8
  }
9
9
 
10
+ def class_name
11
+ @_class_name ||= respond_to?(:name) ? name.split('::').last.downcase : self.class.name.split('::').last.downcase
12
+ end
13
+
14
+ def pluralized_class_name
15
+ @_pluralized_class_name ||= "#{class_name}s"
16
+ end
17
+
10
18
  def full_url(path, attrs = {})
11
- query = URI.encode_www_form DEFAULT_ATTRIBUTES.merge(attrs)
12
- "#{Dribbble::API_URI}#{path}?#{query}"
19
+ "#{Dribbble::API_URI}#{path}?#{URI.encode_www_form attrs}"
20
+ end
21
+
22
+ def full_url_with_default_params(path, attrs = {})
23
+ full_url path, DEFAULT_ATTRIBUTES.merge(attrs)
13
24
  end
14
25
 
15
26
  def headers
@@ -20,20 +31,40 @@ module Dribbble
20
31
  end
21
32
  end
22
33
 
23
- def get(path, attrs = {})
24
- RestClient.get full_url(path, attrs), headers
34
+ def html_get(path, attrs = {})
35
+ res = RestClient.get full_url_with_default_params(path, attrs), headers
36
+ res.force_encoding('UTF-8')
25
37
  rescue RestClient::Unauthorized => e
26
38
  raise Dribbble::Error::Unauthorized, e
27
39
  end
28
40
 
29
- def post(path, attrs = {})
41
+ def html_post(path, attrs = {})
30
42
  payload = {}
31
- yield payload
32
- RestClient.post full_url(path, attrs), payload, headers
43
+ yield payload if block_given?
44
+ res = RestClient.post full_url(path, attrs), payload, headers
45
+ res.force_encoding('UTF-8')
33
46
  rescue RestClient::Unauthorized => e
34
47
  raise Dribbble::Error::Unauthorized, e
35
48
  rescue RestClient::UnprocessableEntity => e
36
49
  raise Dribbble::Error::Unprocessable, e
37
50
  end
51
+
52
+ def html_put(path, attrs = {})
53
+ payload = {}
54
+ yield payload if block_given?
55
+ res = RestClient.put full_url(path, attrs), payload, headers
56
+ res.force_encoding('UTF-8')
57
+ rescue RestClient::Unauthorized => e
58
+ raise Dribbble::Error::Unauthorized, e
59
+ rescue RestClient::UnprocessableEntity => e
60
+ raise Dribbble::Error::Unprocessable, e
61
+ end
62
+
63
+ def html_delete(path, attrs = {})
64
+ res = RestClient.delete full_url(path, attrs), headers
65
+ res.force_encoding('UTF-8')
66
+ rescue RestClient::Unauthorized => e
67
+ raise Dribbble::Error::Unauthorized, e
68
+ end
38
69
  end
39
70
  end
@@ -1,4 +1,4 @@
1
1
  # Dribbble Version
2
2
  module Dribbble
3
- VERSION = '0.0.4'
3
+ VERSION = '1.0.0.beta1'
4
4
  end