dribbble 0.0.4 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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