dimelo_ccp_api 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.ruby-version +1 -0
- data/.travis.yml +15 -0
- data/CHANGELOG.md +29 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +59 -0
- data/Rakefile +23 -0
- data/VERSION +1 -0
- data/dimelo_ccp_api.gemspec +26 -0
- data/examples/dimelo_api_test +34 -0
- data/gemfiles/Gemfile.activesupport-3.2.x +5 -0
- data/gemfiles/Gemfile.activesupport-4.0.x +5 -0
- data/gemfiles/Gemfile.activesupport-4.1.x +5 -0
- data/gemfiles/Gemfile.activesupport-head +5 -0
- data/lib/dimelo/ccp/api/basic_object.rb +17 -0
- data/lib/dimelo/ccp/api/client.rb +46 -0
- data/lib/dimelo/ccp/api/common/openable.rb +23 -0
- data/lib/dimelo/ccp/api/common/publishable.rb +23 -0
- data/lib/dimelo/ccp/api/common/starrable.rb +23 -0
- data/lib/dimelo/ccp/api/connection.rb +86 -0
- data/lib/dimelo/ccp/api/error.rb +71 -0
- data/lib/dimelo/ccp/api/lazzy_collection.rb +114 -0
- data/lib/dimelo/ccp/api/model/answer.rb +39 -0
- data/lib/dimelo/ccp/api/model/attachment.rb +44 -0
- data/lib/dimelo/ccp/api/model/category.rb +12 -0
- data/lib/dimelo/ccp/api/model/category_group.rb +12 -0
- data/lib/dimelo/ccp/api/model/feedback.rb +20 -0
- data/lib/dimelo/ccp/api/model/feedback_comment.rb +31 -0
- data/lib/dimelo/ccp/api/model/membership.rb +12 -0
- data/lib/dimelo/ccp/api/model/private_message.rb +8 -0
- data/lib/dimelo/ccp/api/model/question.rb +20 -0
- data/lib/dimelo/ccp/api/model/role.rb +8 -0
- data/lib/dimelo/ccp/api/model/user.rb +37 -0
- data/lib/dimelo/ccp/api/model/webhook.rb +9 -0
- data/lib/dimelo/ccp/api/model.rb +209 -0
- data/lib/dimelo/ccp/api/version.rb +7 -0
- data/lib/dimelo/ccp/api.rb +62 -0
- data/lib/dimelo_ccp_api.rb +1 -0
- data/spec/examples/openable_examples.rb +37 -0
- data/spec/examples/starrable_example.rb +57 -0
- data/spec/fixtures/files/logo.jpg +0 -0
- data/spec/lib/dimelo/ccp/api/client_spec.rb +111 -0
- data/spec/lib/dimelo/ccp/api/connection_spec.rb +129 -0
- data/spec/lib/dimelo/ccp/api/model/attachment_spec.rb +26 -0
- data/spec/lib/dimelo/ccp/api/model/feedback_spec.rb +10 -0
- data/spec/lib/dimelo/ccp/api/model/question_spec.rb +10 -0
- data/spec/lib/dimelo/ccp/api/model_spec.rb +162 -0
- data/spec/spec_helper.rb +7 -0
- metadata +174 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class Answer < Dimelo::CCP::API::Model
|
3
|
+
include ::Dimelo::CCP::API::Common::Publishable
|
4
|
+
|
5
|
+
path 'questions/%{question_id}/answers/%{id}'
|
6
|
+
|
7
|
+
attributes :id, :body, :body_format, :flow_state, :user_id, :permalink,
|
8
|
+
:attachments_count, :comments_count,
|
9
|
+
:created_at, :updated_at, :question_id, :ipaddr, :question_flow_state
|
10
|
+
|
11
|
+
submit_attributes :body, :body_format, :user_id, :question_id
|
12
|
+
|
13
|
+
belongs_to :user
|
14
|
+
belongs_to :question
|
15
|
+
|
16
|
+
has_many :answer_attachments
|
17
|
+
|
18
|
+
def admin_stamp
|
19
|
+
path = "#{compute_path(attributes)}/admin_stamp"
|
20
|
+
response = client.transport(:post, path)
|
21
|
+
self.attributes = Dimelo::CCP::API.decode_json(response)
|
22
|
+
errors.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def author_stamp
|
26
|
+
path = "#{compute_path(attributes)}/author_stamp"
|
27
|
+
response = client.transport(:post, path)
|
28
|
+
self.attributes = Dimelo::CCP::API.decode_json(response)
|
29
|
+
errors.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def unstamp
|
33
|
+
path = "#{compute_path(attributes)}/stamp"
|
34
|
+
response = client.transport(:delete, path)
|
35
|
+
self.attributes = Dimelo::CCP::API.decode_json(response)
|
36
|
+
errors.empty?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class Attachment < Dimelo::CCP::API::Model
|
3
|
+
attributes :id, :file, :original, :question_id
|
4
|
+
end
|
5
|
+
|
6
|
+
class AnswerAttachment < Attachment
|
7
|
+
path 'questions/%{question_id}/answers/%{answer_id}/attachments/%{id}'
|
8
|
+
|
9
|
+
attributes :id, :file, :original, :answer_id, :question_id
|
10
|
+
|
11
|
+
belongs_to :answer
|
12
|
+
|
13
|
+
submit_attributes :file, :question_id, :answer_id
|
14
|
+
end
|
15
|
+
|
16
|
+
class FeedbackCommentAttachment < Attachment
|
17
|
+
path 'feedbacks/%{feedback_id}/comments/%{comment_id}/attachments/%{id}'
|
18
|
+
|
19
|
+
attributes :id, :file, :original, :feedback_id, :comment_id
|
20
|
+
belongs_to :feedback_comment
|
21
|
+
|
22
|
+
submit_attributes :file, :question_id, :answer_id
|
23
|
+
end
|
24
|
+
|
25
|
+
class QuestionAttachment < Attachment
|
26
|
+
path 'questions/%{question_id}/attachments/%{id}'
|
27
|
+
|
28
|
+
attributes :id, :file, :original, :question_id
|
29
|
+
|
30
|
+
belongs_to :question
|
31
|
+
|
32
|
+
submit_attributes :file, :question_id
|
33
|
+
end
|
34
|
+
|
35
|
+
class FeedbackAttachment < Attachment
|
36
|
+
path 'feedbacks/%{feedback_id}/attachments/%{id}'
|
37
|
+
|
38
|
+
attributes :id, :file, :original, :feedback_id
|
39
|
+
|
40
|
+
belongs_to :question
|
41
|
+
|
42
|
+
submit_attributes :file, :feedback_id
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class Category < Dimelo::CCP::API::Model
|
3
|
+
path 'category_groups/%{category_group_id}/categories/%{id}'
|
4
|
+
|
5
|
+
attributes :id, :category_group_id, :name, :description, :questions_count, :permalink, :picture
|
6
|
+
alias :to_s :name
|
7
|
+
|
8
|
+
belongs_to :category_group
|
9
|
+
has_many :questions
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class Feedback < Dimelo::CCP::API::Model
|
3
|
+
include ::Dimelo::CCP::API::Common::Openable
|
4
|
+
include ::Dimelo::CCP::API::Common::Publishable
|
5
|
+
include ::Dimelo::CCP::API::Common::Starrable
|
6
|
+
|
7
|
+
attributes :id, :title, :body, :body_format, :flow_state, :score, :user_id,
|
8
|
+
:category_id, :category_ids, :category_names, :status_id, :star, :starred_at,
|
9
|
+
:closed, :attachments_count, :comments_count, :positive_votes_count, :negative_votes_count,
|
10
|
+
:permalink, :ipaddr, :created_at, :updated_at
|
11
|
+
|
12
|
+
submit_attributes :title, :body, :body_format, :category_ids, :user_id
|
13
|
+
|
14
|
+
belongs_to :user
|
15
|
+
belongs_to :category
|
16
|
+
has_many :feedback_comments
|
17
|
+
alias :comments :feedback_comments
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class FeedbackComment < Dimelo::CCP::API::Model
|
3
|
+
include ::Dimelo::CCP::API::Common::Publishable
|
4
|
+
|
5
|
+
STATUS_COMMENT_PATH = 'feedbacks/%{feedback_id}/status_comments/%{id}'
|
6
|
+
COMMENT_PATH = 'feedbacks/%{feedback_id}/comments/%{id}'
|
7
|
+
|
8
|
+
path COMMENT_PATH
|
9
|
+
|
10
|
+
attributes :id, :feedback_id, :body, :body_format, :flow_state, :user_id, :type, :status_id, :attachments_count, :created_at, :updated_at, :permalink, :ipaddr
|
11
|
+
submit_attributes :body, :body_format, :user_id, :feedback_id, :status_id
|
12
|
+
|
13
|
+
belongs_to :user
|
14
|
+
belongs_to :feedback
|
15
|
+
|
16
|
+
def create
|
17
|
+
self.class.path(STATUS_COMMENT_PATH) if status_id
|
18
|
+
super
|
19
|
+
ensure
|
20
|
+
self.class.path(COMMENT_PATH) if status_id
|
21
|
+
end
|
22
|
+
|
23
|
+
def update
|
24
|
+
self.class.path(STATUS_COMMENT_PATH) if status_id
|
25
|
+
super
|
26
|
+
ensure
|
27
|
+
self.class.path(COMMENT_PATH) if status_id
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class Membership < Dimelo::CCP::API::Model
|
3
|
+
|
4
|
+
path 'users/%{user_id}/memberships/%{id}'
|
5
|
+
|
6
|
+
attributes :id, :user_id, :role, :domain, :domain_application_id
|
7
|
+
submit_attributes :user_id, :role, :domain
|
8
|
+
|
9
|
+
belongs_to :user
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class PrivateMessage < Dimelo::CCP::API::Model
|
3
|
+
|
4
|
+
attributes :id, :title, :body, :html_body, :raw_body, :from_user_id, :to_user_id, :parent_id, :root_id, :created_at, :updated_at
|
5
|
+
submit_attributes :title, :body, :from_user_id, :to_user_id, :parent_id
|
6
|
+
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class Question < Dimelo::CCP::API::Model
|
3
|
+
include ::Dimelo::CCP::API::Common::Openable
|
4
|
+
include ::Dimelo::CCP::API::Common::Publishable
|
5
|
+
include ::Dimelo::CCP::API::Common::Starrable
|
6
|
+
|
7
|
+
attributes :id, :title, :body, :body_format, :flow_state, :score, :user_id,
|
8
|
+
:ipaddr, :category_id, :category_ids, :category_names, :starred_at,
|
9
|
+
:answers_count, :attachments_count, :usefulnesses_yes_count, :usefulnesses_no_count,
|
10
|
+
:star, :closed, :permalink, :created_at, :updated_at
|
11
|
+
|
12
|
+
submit_attributes :title, :body, :body_format, :category_ids, :user_id
|
13
|
+
|
14
|
+
belongs_to :user
|
15
|
+
belongs_to :category
|
16
|
+
has_many :answers
|
17
|
+
has_many :question_attachments
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class Role < Dimelo::CCP::API::Model
|
3
|
+
|
4
|
+
attributes :id, :label, :team
|
5
|
+
attributes :view_site, :edit_customization, :view_admin, :edit_grids, :send_private_message, :view_analytics, :view_identities, :view_advanced_admin, :configure_extensions, :configure_mobile
|
6
|
+
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class User < Dimelo::CCP::API::Model
|
3
|
+
CUSTOM_FIELD_COUNT = 10
|
4
|
+
CUSTOM_FIELD_ATTRIBUTES = (1..CUSTOM_FIELD_COUNT).map { |i| "custom_field_#{i}".to_sym }.freeze
|
5
|
+
|
6
|
+
attributes :id, :firstname, :lastname, :signature, :email, :private_message, :type, :username, :flow_state, :about, :avatar, :created_at, :updated_at, :blocked, :team
|
7
|
+
attributes *CUSTOM_FIELD_ATTRIBUTES
|
8
|
+
|
9
|
+
submit_attributes :type, :firstname, :lastname, :email, :username, :avatar_url, :about
|
10
|
+
|
11
|
+
has_many :memberships
|
12
|
+
has_many :questions
|
13
|
+
has_many :answers
|
14
|
+
has_many :feedbacks
|
15
|
+
|
16
|
+
def avatar_url(size='normal')
|
17
|
+
avatar.try(:[], size).try(:[], 'url')
|
18
|
+
end
|
19
|
+
|
20
|
+
# Blocks the specified user
|
21
|
+
def block
|
22
|
+
path = "#{compute_path(attributes)}/block"
|
23
|
+
response = client.transport(:post, path)
|
24
|
+
self.attributes = Dimelo::CCP::API.decode_json(response)
|
25
|
+
errors.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Unblocks the specified user
|
29
|
+
def unblock
|
30
|
+
path = "#{compute_path(attributes)}/unblock"
|
31
|
+
response = client.transport(:post, path)
|
32
|
+
self.attributes = Dimelo::CCP::API.decode_json(response)
|
33
|
+
errors.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Dimelo::CCP
|
2
|
+
class Webhook < Dimelo::CCP::API::Model
|
3
|
+
|
4
|
+
attributes :id, :endpoint_enabled, :endpoint_url, :preprod_settings, :verify_token
|
5
|
+
attributes :answer__destroyed, :question__destroyed, :identity__destroyed, :comment__destroyed, :feedback__destroyed, :status_comment__destroyed
|
6
|
+
|
7
|
+
submit_attributes :id, :endpoint_enabled, :endpoint_url, :preprod_settings, :verify_token, :answer__destroyed, :question__destroyed, :identity__destroyed, :comment__destroyed, :feedback__destroyed, :status_comment__destroyed
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module Dimelo::CCP
|
4
|
+
module API
|
5
|
+
class Model
|
6
|
+
extend ActiveModel::Translation
|
7
|
+
extend ActiveModel::Naming
|
8
|
+
include ActiveModel::Validations
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def path(*args)
|
13
|
+
@path = args.first if args.any?
|
14
|
+
@path ||= "#{name.demodulize.pluralize.underscore}/%{id}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def attribute(arg)
|
18
|
+
@attributes ||= []
|
19
|
+
@attributes << arg
|
20
|
+
attr_reader(arg)
|
21
|
+
class_eval "
|
22
|
+
def #{arg}=(val)
|
23
|
+
@tracked_attributes << :#{arg}
|
24
|
+
@#{arg} = val
|
25
|
+
end"
|
26
|
+
end
|
27
|
+
|
28
|
+
def attributes(*args)
|
29
|
+
args.each do |arg|
|
30
|
+
attribute arg
|
31
|
+
end
|
32
|
+
@attributes
|
33
|
+
end
|
34
|
+
|
35
|
+
def submit_attributes(*args)
|
36
|
+
@submit_attributes = args if args.any?
|
37
|
+
@submit_attributes ||= []
|
38
|
+
end
|
39
|
+
|
40
|
+
def has_many(association, options={})
|
41
|
+
foreign_class = options[:class_name] || "#{name.gsub(/(\w+)$/, '')}#{association.to_s.singularize.camelize}"
|
42
|
+
foreign_reference = self.name.demodulize.underscore
|
43
|
+
foreign_key = "#{foreign_reference}_id"
|
44
|
+
|
45
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
46
|
+
|
47
|
+
def #{association}(client=nil)
|
48
|
+
# FIXME: clear cache if client change, or something like that
|
49
|
+
client ||= @client
|
50
|
+
@#{association} ||= #{foreign_class}.find({:#{foreign_key} => self.id}, client).each do |instance|
|
51
|
+
instance.#{foreign_reference} = self
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def #{association}=(items)
|
56
|
+
@#{association} = items.each{ |i| i.#{foreign_reference} = self }
|
57
|
+
end
|
58
|
+
|
59
|
+
EOS
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
def belongs_to(association, options={})
|
64
|
+
attr_writer association
|
65
|
+
foreign_class = options[:class_name] || "#{name.gsub(/(\w+)$/, '')}#{association.to_s.camelize}"
|
66
|
+
foreign_reference = self.name.demodulize.underscore
|
67
|
+
foreign_key = "#{association}_id"
|
68
|
+
|
69
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
70
|
+
|
71
|
+
def #{association}(client=nil)
|
72
|
+
client ||= @client
|
73
|
+
@#{association} ||= #{foreign_class}.find(self.#{foreign_key}, client)
|
74
|
+
end
|
75
|
+
|
76
|
+
EOS
|
77
|
+
end
|
78
|
+
|
79
|
+
def find(*args)
|
80
|
+
client = args.pop
|
81
|
+
criterias = args.pop
|
82
|
+
criterias = {:id => criterias} unless criterias.is_a?(Hash)
|
83
|
+
Dimelo::CCP::API::LazzyCollection.new(criterias) do |criterias|
|
84
|
+
parse(client.transport(:get, compute_path(criterias), criterias), client)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse(document, client=nil)
|
89
|
+
object = Dimelo::CCP::API.decode_json(document)
|
90
|
+
object.is_a?(Array) ? object.map{ |i| new(i, client) } : new(object, client)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Inspired by https://github.com/svenfuchs/i18n/blob/master/lib/i18n/core_ext/string/interpolate.rb
|
94
|
+
INTERPOLATION_PATTERN = /%\{(\w+)\}/ # matches placeholders like "%{foo}"
|
95
|
+
def compute_path(criterias={})
|
96
|
+
path.gsub(INTERPOLATION_PATTERN) do |match|
|
97
|
+
criterias.delete($1.to_sym) || ''
|
98
|
+
end.chomp '/'
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
attr_accessor :client
|
104
|
+
attr_reader :errors, :tracked_attributes
|
105
|
+
|
106
|
+
delegate :compute_path, :to => 'self.class'
|
107
|
+
|
108
|
+
def initialize(hash={}, client=nil)
|
109
|
+
@errors = ActiveModel::Errors.new(self)
|
110
|
+
@tracked_attributes = []
|
111
|
+
self.client = client
|
112
|
+
hash.each do |k,v|
|
113
|
+
self.send("#{k}=", v) if self.respond_to?("#{k}=")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def errors=(errs)
|
118
|
+
@errors = ActiveModel::Errors.new(self).tap do |errors|
|
119
|
+
errs.each do |error|
|
120
|
+
errors.add(error['attribute'], error['type'])
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def attributes
|
126
|
+
Hash[self.class.attributes.map{ |key| [key, self.send(key)] }]
|
127
|
+
end
|
128
|
+
|
129
|
+
def attributes=(hash)
|
130
|
+
hash.each do |k, value|
|
131
|
+
if self.respond_to? "#{k}="
|
132
|
+
self.send("#{k}=", value)
|
133
|
+
else
|
134
|
+
warn("Unknown field or method #{k} for object #{self.inspect}")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def tracked_submit_attributes
|
140
|
+
@tracked_attributes & self.class.submit_attributes
|
141
|
+
end
|
142
|
+
|
143
|
+
def submit_attributes
|
144
|
+
Hash[tracked_submit_attributes.map{ |key| [key, self.send(key)] }]
|
145
|
+
end
|
146
|
+
|
147
|
+
def new_record?
|
148
|
+
id.blank?
|
149
|
+
end
|
150
|
+
|
151
|
+
def save
|
152
|
+
if new_record?
|
153
|
+
create
|
154
|
+
else
|
155
|
+
update
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def create
|
160
|
+
attrs = submit_attributes
|
161
|
+
path = compute_path(attrs)
|
162
|
+
response = client.transport(:post, path, attrs)
|
163
|
+
self.attributes = Dimelo::CCP::API.decode_json(response)
|
164
|
+
id.present?
|
165
|
+
end
|
166
|
+
|
167
|
+
def update
|
168
|
+
attrs = submit_attributes
|
169
|
+
path = compute_path(attributes)
|
170
|
+
response = client.transport(:put, path, attrs)
|
171
|
+
self.attributes = Dimelo::CCP::API.decode_json(response)
|
172
|
+
errors.empty?
|
173
|
+
end
|
174
|
+
|
175
|
+
def valid?
|
176
|
+
true
|
177
|
+
end
|
178
|
+
|
179
|
+
def destroy
|
180
|
+
client.transport(:delete, compute_path(self.attributes))
|
181
|
+
freeze
|
182
|
+
end
|
183
|
+
|
184
|
+
def reload
|
185
|
+
raise ArgumentError.new("You cannot fetch models without a populated id attribute") if id.nil?
|
186
|
+
other = self.class.find(id, client)
|
187
|
+
self.attributes.merge!(other.attributes) if other
|
188
|
+
self
|
189
|
+
end
|
190
|
+
|
191
|
+
def ==(other)
|
192
|
+
other.is_a?(self.class) and self.id == other.id and self.id.present?
|
193
|
+
end
|
194
|
+
|
195
|
+
def merge!(other)
|
196
|
+
self.attributes = other.attributes
|
197
|
+
end
|
198
|
+
|
199
|
+
def to_json
|
200
|
+
Dimelo::CCP::API.encode_json(self.attributes)
|
201
|
+
end
|
202
|
+
|
203
|
+
def warn(message)
|
204
|
+
defined?(Rails) ? Rails.logger.warn(message) : STDERR.puts(message)
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/json'
|
3
|
+
require 'active_support/core_ext'
|
4
|
+
require 'faraday'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
module Dimelo
|
8
|
+
module CCP
|
9
|
+
|
10
|
+
autoload :Answer, 'dimelo/ccp/api/model/answer'
|
11
|
+
autoload :Attachment, 'dimelo/ccp/api/model/attachment'
|
12
|
+
autoload :Category, 'dimelo/ccp/api/model/category'
|
13
|
+
autoload :CategoryGroup, 'dimelo/ccp/api/model/category_group'
|
14
|
+
autoload :Feedback, 'dimelo/ccp/api/model/feedback'
|
15
|
+
autoload :FeedbackComment,'dimelo/ccp/api/model/feedback_comment'
|
16
|
+
autoload :Membership, 'dimelo/ccp/api/model/membership'
|
17
|
+
autoload :PrivateMessage, 'dimelo/ccp/api/model/private_message'
|
18
|
+
autoload :Question, 'dimelo/ccp/api/model/question'
|
19
|
+
autoload :Role, 'dimelo/ccp/api/model/role'
|
20
|
+
autoload :User, 'dimelo/ccp/api/model/user'
|
21
|
+
autoload :Webhook, 'dimelo/ccp/api/model/webhook'
|
22
|
+
|
23
|
+
# Attachments
|
24
|
+
autoload :AnswerAttachment, 'dimelo/ccp/api/model/attachment'
|
25
|
+
autoload :CommentAttachment, 'dimelo/ccp/api/model/attachment'
|
26
|
+
autoload :FeedbackAttachment, 'dimelo/ccp/api/model/attachment'
|
27
|
+
autoload :FeedbackCommentAttachment, 'dimelo/ccp/api/model/attachment'
|
28
|
+
autoload :QuestionAttachment, 'dimelo/ccp/api/model/attachment'
|
29
|
+
|
30
|
+
module API
|
31
|
+
|
32
|
+
autoload :VERSION, 'dimelo/ccp/api/version'
|
33
|
+
autoload :Client, 'dimelo/ccp/api/client'
|
34
|
+
autoload :Connection, 'dimelo/ccp/api/connection'
|
35
|
+
autoload :Model, 'dimelo/ccp/api/model'
|
36
|
+
autoload :BasicObject, 'dimelo/ccp/api/basic_object'
|
37
|
+
autoload :LazzyCollection, 'dimelo/ccp/api/lazzy_collection'
|
38
|
+
|
39
|
+
require 'dimelo/ccp/api/error'
|
40
|
+
|
41
|
+
class << self
|
42
|
+
|
43
|
+
def decode_json(document)
|
44
|
+
ActiveSupport::JSON.decode(document)
|
45
|
+
end
|
46
|
+
|
47
|
+
def encode_json(object)
|
48
|
+
ActiveSupport::JSON.encode(object)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
module Common
|
54
|
+
|
55
|
+
autoload :Openable, 'dimelo/ccp/api/common/openable'
|
56
|
+
autoload :Publishable, 'dimelo/ccp/api/common/publishable'
|
57
|
+
autoload :Starrable, 'dimelo/ccp/api/common/starrable'
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'dimelo/ccp/api'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
shared_examples_for 'common model actions' do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@response = {'title' => 'new title'}.to_json
|
7
|
+
@client = double
|
8
|
+
allow(@client).to receive(:transport) { @response }
|
9
|
+
@content = described_class.new({'id' => 123, 'title' => 'old title'}, @client)
|
10
|
+
allow(@content).to receive(:errors) { [] }
|
11
|
+
end
|
12
|
+
|
13
|
+
%w(open close publish unpublish).each do |action|
|
14
|
+
describe action do
|
15
|
+
|
16
|
+
it 'sends a put to the appropriate uri' do
|
17
|
+
path = @content.compute_path(@content.attributes) + "/#{action}"
|
18
|
+
expect(@client).to receive(:transport).with(:put, path).and_return(@response)
|
19
|
+
@content.send(action)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'updates the object with the new attributes' do
|
23
|
+
expect {
|
24
|
+
@content.send(action)
|
25
|
+
}.to change { @content.title }.from('old title').to('new title')
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns a boolean indicating any errors' do
|
29
|
+
expect {
|
30
|
+
allow(@content).to receive(:errors) { ['uh-oh'] }
|
31
|
+
}.to change { @content.send(action) }.from(true).to(false)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
shared_examples_for 'starrable object' do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@response = {'title' => 'new title'}.to_json
|
7
|
+
@client = double
|
8
|
+
allow(@client).to receive(:transport) { @response }
|
9
|
+
@content = described_class.new({'id' => 123, 'title' => 'old title'}, @client)
|
10
|
+
allow(@content).to receive(:errors) { [] }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#star!' do
|
14
|
+
|
15
|
+
it 'sends a put to the appropriate uri' do
|
16
|
+
path = @content.compute_path(@content.attributes) + "/star"
|
17
|
+
expect(@client).to receive(:transport).with(:put, path).and_return(@response)
|
18
|
+
@content.star!
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'updates the object with the new attributes' do
|
22
|
+
expect {
|
23
|
+
@content.star!
|
24
|
+
}.to change { @content.title }.from('old title').to('new title')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns a boolean indicating any errors' do
|
28
|
+
expect {
|
29
|
+
allow(@content).to receive(:errors) { ['uh-oh'] }
|
30
|
+
}.to change { @content.star! }.from(true).to(false)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#unstar!' do
|
36
|
+
|
37
|
+
it 'sends a put to the appropriate uri' do
|
38
|
+
path = @content.compute_path(@content.attributes) + "/unstar"
|
39
|
+
expect(@client).to receive(:transport).with(:put, path).and_return(@response)
|
40
|
+
@content.unstar!
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'updates the object with the new attributes' do
|
44
|
+
expect {
|
45
|
+
@content.unstar!
|
46
|
+
}.to change { @content.title }.from('old title').to('new title')
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns a boolean indicating any errors' do
|
50
|
+
expect {
|
51
|
+
allow(@content).to receive(:errors) { ['uh-oh'] }
|
52
|
+
}.to change { @content.unstar! }.from(true).to(false)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
Binary file
|