podio 0.8.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/Gemfile +9 -2
- data/README.md +1 -4
- data/examples/oauth_web_flow/Gemfile +4 -0
- data/examples/{sinatra.rb → oauth_web_flow/sinatra.rb} +7 -6
- data/lib/podio.rb +18 -3
- data/lib/podio/active_podio/base.rb +107 -62
- data/lib/podio/client.rb +30 -5
- data/lib/podio/error.rb +22 -10
- data/lib/podio/middleware/error_response.rb +23 -16
- data/lib/podio/middleware/json_response.rb +1 -1
- data/lib/podio/middleware/logger.rb +3 -0
- data/lib/podio/middleware/oauth2.rb +3 -0
- data/lib/podio/models/account_provider.rb +1 -0
- data/lib/podio/models/action.rb +19 -2
- data/lib/podio/models/activation_status.rb +8 -2
- data/lib/podio/models/app_store_category.rb +4 -1
- data/lib/podio/models/app_store_share.rb +29 -16
- data/lib/podio/models/application.rb +57 -2
- data/lib/podio/models/application_email.rb +5 -2
- data/lib/podio/models/application_field.rb +5 -2
- data/lib/podio/models/batch.rb +8 -0
- data/lib/podio/models/by_line.rb +2 -1
- data/lib/podio/models/calendar_event.rb +63 -3
- data/lib/podio/models/calendar_mute.rb +6 -1
- data/lib/podio/models/category.rb +1 -0
- data/lib/podio/models/comment.rb +29 -8
- data/lib/podio/models/condition.rb +8 -0
- data/lib/podio/models/condition_set.rb +40 -0
- data/lib/podio/models/contact.rb +13 -2
- data/lib/podio/models/contract.rb +85 -1
- data/lib/podio/models/contract_event.rb +17 -0
- data/lib/podio/models/contract_price.rb +3 -7
- data/lib/podio/models/contract_price_v2.rb +31 -0
- data/lib/podio/models/contract_user.rb +4 -0
- data/lib/podio/models/conversation.rb +114 -13
- data/lib/podio/models/conversation_event.rb +51 -0
- data/lib/podio/models/conversation_message.rb +2 -1
- data/lib/podio/models/conversation_participant.rb +3 -2
- data/lib/podio/models/date_election.rb +35 -0
- data/lib/podio/models/email_contact.rb +46 -0
- data/lib/podio/models/email_subscription_setting.rb +4 -23
- data/lib/podio/models/embed.rb +4 -4
- data/lib/podio/models/experiment.rb +71 -0
- data/lib/podio/models/external_file.rb +7 -2
- data/lib/podio/models/file_attachment.rb +23 -0
- data/lib/podio/models/form.rb +7 -0
- data/lib/podio/models/friend.rb +12 -0
- data/lib/podio/models/grant.rb +73 -0
- data/lib/podio/models/hook.rb +13 -6
- data/lib/podio/models/importer.rb +3 -0
- data/lib/podio/models/integration.rb +17 -6
- data/lib/podio/models/invoice.rb +30 -0
- data/lib/podio/models/item.rb +81 -14
- data/lib/podio/models/item_diff.rb +9 -5
- data/lib/podio/models/item_field.rb +11 -2
- data/lib/podio/models/item_revision.rb +5 -2
- data/lib/podio/models/linked_account.rb +1 -0
- data/lib/podio/models/live.rb +61 -0
- data/lib/podio/models/net_promoter_score.rb +28 -0
- data/lib/podio/models/notification.rb +9 -4
- data/lib/podio/models/notification_group.rb +5 -2
- data/lib/podio/models/o_auth.rb +4 -2
- data/lib/podio/models/o_auth_client.rb +1 -2
- data/lib/podio/models/organization.rb +22 -10
- data/lib/podio/models/organization_contact.rb +2 -1
- data/lib/podio/models/organization_member.rb +17 -3
- data/lib/podio/models/organization_profile.rb +8 -2
- data/lib/podio/models/pin.rb +27 -0
- data/lib/podio/models/profile.rb +19 -50
- data/lib/podio/models/promotion.rb +91 -0
- data/lib/podio/models/rating.rb +23 -5
- data/lib/podio/models/recurrence.rb +6 -3
- data/lib/podio/models/reference.rb +17 -1
- data/lib/podio/models/reminder.rb +8 -3
- data/lib/podio/models/search.rb +7 -1
- data/lib/podio/models/space.rb +41 -2
- data/lib/podio/models/space_contact.rb +1 -2
- data/lib/podio/models/space_invitation.rb +4 -5
- data/lib/podio/models/space_member.rb +37 -4
- data/lib/podio/models/status.rb +20 -8
- data/lib/podio/models/stream_activity_group.rb +40 -0
- data/lib/podio/models/stream_mute.rb +7 -8
- data/lib/podio/models/stream_object.rb +19 -11
- data/lib/podio/models/subscription.rb +7 -1
- data/lib/podio/models/tag.rb +6 -1
- data/lib/podio/models/tag_search.rb +2 -1
- data/lib/podio/models/task.rb +74 -18
- data/lib/podio/models/task_label.rb +10 -2
- data/lib/podio/models/user.rb +50 -6
- data/lib/podio/models/user_mail.rb +4 -0
- data/lib/podio/models/user_status.rb +7 -0
- data/lib/podio/models/view.rb +27 -7
- data/lib/podio/models/widget.rb +25 -3
- data/lib/podio/version.rb +1 -1
- data/podio.gemspec +13 -10
- data/script/config.example.rb +6 -0
- data/script/referenceGenerator.rb +87 -0
- data/test/active_podio_test.rb +44 -34
- data/test/client_test.rb +13 -2
- metadata +89 -36
- data/lib/podio/middleware/date_conversion.rb +0 -37
- data/lib/podio/models/bulletin.rb +0 -60
- data/lib/podio/models/connection.rb +0 -53
- data/lib/podio/models/news.rb +0 -85
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ddca0ab27daadb721f418559e369f9df19ff079b
|
4
|
+
data.tar.gz: 62879f0a0051374d7edf58585fb23fcdc1b8a65f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 745846890f8a4a11a0ae2591db7d2921ab9fa33cb696b7573aedb7de87c46ddbf4966f16d97132e7da7e13756dff437eb48ae2dff15b34a6e7eed5509fd3550b
|
7
|
+
data.tar.gz: b1bd3c5b7177185fa91b198f88b05ebd51820c30a4fca4fb00f7f0feab151b2afa3ab2aa013f9881b623ba17eb5db3632be90a302585eeb9263c42a6f0c0297c
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -113,7 +113,7 @@ All unsuccessful responses returned by the API (everything that has a 4xx or 5xx
|
|
113
113
|
puts exc.url # uri of the API request
|
114
114
|
|
115
115
|
# you normally want this one, a human readable error description
|
116
|
-
puts exc.
|
116
|
+
puts exc.message
|
117
117
|
end
|
118
118
|
|
119
119
|
On instance methods, however, exceptions are handled in a way similar to ActiveRecord. These methods returns a boolean indicating if the API request succeeded or not, and makes the code, description and parameters available when the request fails:
|
@@ -146,9 +146,6 @@ Full Example
|
|
146
146
|
puts org.url
|
147
147
|
end
|
148
148
|
|
149
|
-
Note on Heroku Usage
|
150
|
-
--------------------
|
151
|
-
If you plan on using podio-rb on Heroku please note that only the 1.9.2 stack has been tested. Specifically, bamboo-mri-1.9.2 is recommended, while 1.8.7 is still stock on Heroku. Refer to their documentation for information on how to migrate your dynos
|
152
149
|
|
153
150
|
Meta
|
154
151
|
----
|
@@ -18,11 +18,12 @@ require 'sinatra'
|
|
18
18
|
require 'podio'
|
19
19
|
|
20
20
|
|
21
|
-
|
22
|
-
Podio.setup(
|
23
|
-
|
24
|
-
|
25
|
-
)
|
21
|
+
before do
|
22
|
+
Podio.setup(
|
23
|
+
:api_key => 'YOUR_API_KEY', # CHANGE this this to make this example work
|
24
|
+
:api_secret => 'YOUR_API_SECRET' # CHANGE this this to make this example work
|
25
|
+
)
|
26
|
+
end
|
26
27
|
|
27
28
|
get '/' do
|
28
29
|
%(<p>Update the <code>Podio.setup</code> call in the sinatra app and <a href="/auth/podio">try to authorize</a>.</p>)
|
@@ -50,6 +51,6 @@ end
|
|
50
51
|
|
51
52
|
def redirect_uri(path='/auth/podio/callback')
|
52
53
|
uri = URI.parse(request.url)
|
53
|
-
uri.path
|
54
|
+
uri.path = path
|
54
55
|
uri.to_s
|
55
56
|
end
|
data/lib/podio.rb
CHANGED
@@ -2,8 +2,8 @@ require 'faraday'
|
|
2
2
|
require 'active_support/core_ext'
|
3
3
|
|
4
4
|
require 'podio/error'
|
5
|
+
require 'podio/version'
|
5
6
|
require 'podio/middleware/json_request'
|
6
|
-
#require 'podio/middleware/date_conversion'
|
7
7
|
require 'podio/middleware/logger'
|
8
8
|
require 'podio/middleware/oauth2'
|
9
9
|
require 'podio/middleware/json_response'
|
@@ -76,36 +76,48 @@ module Podio
|
|
76
76
|
autoload :ApplicationField, 'podio/models/application_field'
|
77
77
|
autoload :AccountProvider, 'podio/models/account_provider'
|
78
78
|
autoload :Batch, 'podio/models/batch'
|
79
|
-
autoload :Bulletin, 'podio/models/bulletin'
|
80
79
|
autoload :ByLine, 'podio/models/by_line'
|
81
80
|
autoload :CalendarEvent, 'podio/models/calendar_event'
|
82
81
|
autoload :CalendarMute, 'podio/models/calendar_mute'
|
83
82
|
autoload :Category, 'podio/models/category'
|
84
83
|
autoload :Comment, 'podio/models/comment'
|
84
|
+
autoload :Condition, 'podio/models/condition'
|
85
|
+
autoload :ConditionSet, 'podio/models/condition_set'
|
85
86
|
autoload :Connection, 'podio/models/connection'
|
86
87
|
autoload :Contact, 'podio/models/contact'
|
87
88
|
autoload :Contract, 'podio/models/contract'
|
88
89
|
autoload :ContractAccounting, 'podio/models/contract_accounting'
|
90
|
+
autoload :ContractEvent, 'podio/models/contract_event'
|
89
91
|
autoload :ContractPrice, 'podio/models/contract_price'
|
92
|
+
autoload :ContractPriceV2, 'podio/models/contract_price_v2'
|
93
|
+
autoload :ContractUser, 'podio/models/contract_user'
|
90
94
|
autoload :Conversation, 'podio/models/conversation'
|
95
|
+
autoload :ConversationEvent, 'podio/models/conversation_event'
|
91
96
|
autoload :ConversationMessage, 'podio/models/conversation_message'
|
92
97
|
autoload :ConversationParticipant, 'podio/models/conversation_participant'
|
98
|
+
autoload :DateElection, 'podio/models/date_election'
|
93
99
|
autoload :EmailSubscriptionSetting, 'podio/models/email_subscription_setting'
|
100
|
+
autoload :EmailContact, 'podio/models/email_contact'
|
94
101
|
autoload :Embed, 'podio/models/embed'
|
102
|
+
autoload :Experiment, 'podio/models/experiment'
|
95
103
|
autoload :ExternalFile, 'podio/models/external_file'
|
96
104
|
autoload :FileAttachment, 'podio/models/file_attachment'
|
97
105
|
autoload :Filter, 'podio/models/filter'
|
98
106
|
autoload :Form, 'podio/models/form'
|
107
|
+
autoload :Friend, 'podio/models/friend'
|
108
|
+
autoload :Grant, 'podio/models/grant'
|
99
109
|
autoload :Hook, 'podio/models/hook'
|
100
110
|
autoload :Importer, 'podio/models/importer'
|
101
111
|
autoload :Integration, 'podio/models/integration'
|
112
|
+
autoload :Invoice, 'podio/models/invoice'
|
102
113
|
autoload :Item, 'podio/models/item'
|
103
114
|
autoload :ItemDiff, 'podio/models/item_diff'
|
104
115
|
autoload :ItemField, 'podio/models/item_field'
|
105
116
|
autoload :ItemRevision, 'podio/models/item_revision'
|
106
117
|
autoload :LinkedAccount, 'podio/models/linked_account'
|
107
118
|
autoload :LinkedAccountData, 'podio/models/linked_account_data'
|
108
|
-
autoload :
|
119
|
+
autoload :Live, 'podio/models/live'
|
120
|
+
autoload :NetPromoterScore, 'podio/models/net_promoter_score'
|
109
121
|
autoload :Notification, 'podio/models/notification'
|
110
122
|
autoload :NotificationGroup, 'podio/models/notification_group'
|
111
123
|
autoload :OAuth, 'podio/models/o_auth'
|
@@ -114,7 +126,9 @@ module Podio
|
|
114
126
|
autoload :OrganizationContact, 'podio/models/organization_contact'
|
115
127
|
autoload :OrganizationMember, 'podio/models/organization_member'
|
116
128
|
autoload :OrganizationProfile, 'podio/models/organization_profile'
|
129
|
+
autoload :Pin, 'podio/models/pin'
|
117
130
|
autoload :Profile, 'podio/models/profile'
|
131
|
+
autoload :Promotion, 'podio/models/promotion'
|
118
132
|
autoload :Question, 'podio/models/question'
|
119
133
|
autoload :QuestionAnswer, 'podio/models/question_answer'
|
120
134
|
autoload :QuestionOption, 'podio/models/question_option'
|
@@ -131,6 +145,7 @@ module Podio
|
|
131
145
|
autoload :Status, 'podio/models/status'
|
132
146
|
autoload :StreamMute, 'podio/models/stream_mute'
|
133
147
|
autoload :StreamObject, 'podio/models/stream_object'
|
148
|
+
autoload :StreamActivityGroup, 'podio/models/stream_activity_group'
|
134
149
|
autoload :Subscription, 'podio/models/subscription'
|
135
150
|
autoload :Tag, 'podio/models/tag'
|
136
151
|
autoload :TagSearch, 'podio/models/tag_search'
|
@@ -6,12 +6,15 @@ module ActivePodio
|
|
6
6
|
extend ActiveModel::Naming, ActiveModel::Callbacks
|
7
7
|
include ActiveModel::Conversion
|
8
8
|
|
9
|
-
class_attribute :valid_attributes, :
|
10
|
-
|
11
|
-
|
9
|
+
class_attribute :valid_attributes, :json_attributes, :_associations
|
10
|
+
|
11
|
+
self.valid_attributes = []
|
12
|
+
self.json_attributes = []
|
13
|
+
self._associations = {}
|
14
|
+
|
15
|
+
attr_accessor :attributes
|
12
16
|
|
13
17
|
def initialize(attributes = {}, options = {})
|
14
|
-
self.valid_attributes ||= []
|
15
18
|
attributes = {} if attributes.blank?
|
16
19
|
self.attributes = Hash[*self.valid_attributes.collect { |n| [n.to_sym, nil] }.flatten].merge(attributes.symbolize_keys)
|
17
20
|
|
@@ -28,11 +31,20 @@ module ActivePodio
|
|
28
31
|
if self.respond_to?("#{key}=".to_sym)
|
29
32
|
self.send("#{key}=".to_sym, value)
|
30
33
|
else
|
31
|
-
is_association_hash = value.is_a?(Hash) && self._associations.
|
34
|
+
is_association_hash = value.is_a?(Hash) && self._associations.has_key?(key.to_sym) && self._associations[key.to_sym] == :has_one && (self.send(key.to_sym).respond_to?(:attributes) || self.send(key.to_sym).nil?)
|
32
35
|
if valid_attributes.include?(key.to_sym) || is_association_hash
|
36
|
+
|
33
37
|
# Initialize nested object to get correctly casted values set back, unless the given values are all blank
|
34
38
|
if is_association_hash
|
35
|
-
|
39
|
+
# Merge existing values with given values and do recursive initalize call to get values casted correctly
|
40
|
+
if self.send(key.to_sym).present?
|
41
|
+
existing_attributes = self.send(key.to_sym).try(:attributes) || {}
|
42
|
+
value.reverse_merge!(existing_attributes)
|
43
|
+
self.send(key.to_sym).initialize_attributes(value)
|
44
|
+
else
|
45
|
+
self.send(:[]=, key.to_sym, value)
|
46
|
+
end
|
47
|
+
|
36
48
|
attributes = self.send(key.to_sym).try(:attributes)
|
37
49
|
if attributes.present? && any_values_present_recursive?(attributes.values)
|
38
50
|
value = attributes
|
@@ -68,7 +80,7 @@ module ActivePodio
|
|
68
80
|
def []=(attribute, value)
|
69
81
|
@attributes ||= {}
|
70
82
|
@attributes[attribute.to_sym] = value
|
71
|
-
if @belongs_to.present? && value.present?
|
83
|
+
if @belongs_to.present? && @belongs_to[:model].present? && @belongs_to[:as].present? && value.present?
|
72
84
|
@belongs_to[:model][@belongs_to[:as]] ||= {}
|
73
85
|
@belongs_to[:model][@belongs_to[:as]][attribute.to_sym] = value
|
74
86
|
end
|
@@ -89,18 +101,27 @@ module ActivePodio
|
|
89
101
|
result.merge!(:id => self.id) if self.respond_to?(:id)
|
90
102
|
|
91
103
|
if options[:formatted]
|
92
|
-
(self.valid_attributes +
|
104
|
+
(self.valid_attributes + self.json_attributes).uniq.each do |name|
|
93
105
|
result[name] = json_friendly_value(self.send(name), options)
|
94
106
|
end
|
95
107
|
|
96
108
|
unless options[:nested] == false
|
97
|
-
|
98
|
-
self.
|
109
|
+
self._associations.each do |name, type|
|
110
|
+
nested_value = self.send(name)
|
111
|
+
unless nested_value.nil?
|
112
|
+
nested_options = options.except(:methods)
|
113
|
+
if options[:methods].present? && options[:methods].respond_to?(:find)
|
114
|
+
methods_hash = options[:methods].find { |method| method.is_a?(Hash) }
|
115
|
+
if methods_hash.present?
|
116
|
+
nested_methods = methods_hash[name]
|
117
|
+
nested_options.merge!(:methods => nested_methods) if nested_methods.present?
|
118
|
+
end
|
119
|
+
end
|
99
120
|
case type
|
100
121
|
when :has_one
|
101
|
-
result[name] =
|
122
|
+
result[name] = nested_value.as_json(nested_options)
|
102
123
|
when :has_many
|
103
|
-
result[name] =
|
124
|
+
result[name] = nested_value.collect { |assoc| assoc.as_json(nested_options) }
|
104
125
|
end
|
105
126
|
end
|
106
127
|
end
|
@@ -111,7 +132,7 @@ module ActivePodio
|
|
111
132
|
|
112
133
|
if options[:methods]
|
113
134
|
options[:methods].each do |name|
|
114
|
-
result[name] = json_friendly_value(self.send(name), options)
|
135
|
+
result[name] = json_friendly_value(self.send(name), options.except(:methods) ) unless name.is_a?(Hash)
|
115
136
|
end
|
116
137
|
end
|
117
138
|
|
@@ -120,17 +141,26 @@ module ActivePodio
|
|
120
141
|
|
121
142
|
# Override this in models where the class name doesn't match the ref type
|
122
143
|
def api_friendly_ref_type
|
123
|
-
self.class.name.
|
144
|
+
self.class.name.demodulize.parameterize
|
145
|
+
end
|
146
|
+
|
147
|
+
def parent_model
|
148
|
+
@belongs_to[:model] if @belongs_to.present?
|
124
149
|
end
|
125
150
|
|
126
151
|
private
|
127
152
|
|
128
153
|
def klass_for_association(options)
|
129
154
|
klass_name = options[:class]
|
155
|
+
|
156
|
+
if !klass_name.present? && options[:class_map].present?
|
157
|
+
class_property = options[:class_property] || :type
|
158
|
+
class_property_value = self.send(class_property).try(:to_sym)
|
159
|
+
klass_name = options[:class_map][class_property_value]
|
160
|
+
end
|
161
|
+
|
130
162
|
raise "Missing class name of associated model. Provide with :class => 'MyClass'." unless klass_name.present?
|
131
|
-
|
132
|
-
klass = "Podio::#{klass_name}".constantize unless klass.respond_to?(:ancestors) && klass.ancestors.include?(ActivePodio::Base)
|
133
|
-
return klass
|
163
|
+
return self.class.klass_from_string(klass_name)
|
134
164
|
end
|
135
165
|
|
136
166
|
def any_values_present_recursive?(values)
|
@@ -145,7 +175,7 @@ module ActivePodio
|
|
145
175
|
|
146
176
|
def json_friendly_value(ruby_value, options)
|
147
177
|
if options[:formatted]
|
148
|
-
|
178
|
+
case ruby_value.class.name
|
149
179
|
when "DateTime", "Time"
|
150
180
|
ruby_value.iso8601
|
151
181
|
when "Array"
|
@@ -153,9 +183,11 @@ module ActivePodio
|
|
153
183
|
when "Hash"
|
154
184
|
ruby_value.each { |key, value| ruby_value[key] = json_friendly_value(value, options) }
|
155
185
|
ruby_value
|
186
|
+
when "BigDecimal"
|
187
|
+
ruby_value.to_f # No Decimal in Javascript, Float is better than String
|
156
188
|
else
|
157
189
|
if ruby_value.kind_of?(ActivePodio::Base)
|
158
|
-
ruby_value.as_json(options)
|
190
|
+
ruby_value.as_json(options.except(:methods))
|
159
191
|
else
|
160
192
|
ruby_value
|
161
193
|
end
|
@@ -163,6 +195,7 @@ module ActivePodio
|
|
163
195
|
else
|
164
196
|
ruby_value
|
165
197
|
end
|
198
|
+
|
166
199
|
end
|
167
200
|
|
168
201
|
class << self
|
@@ -171,8 +204,7 @@ module ActivePodio
|
|
171
204
|
|
172
205
|
# Defines the the supported attributes of the model
|
173
206
|
def property(name, type = :string, options = {})
|
174
|
-
self.valid_attributes
|
175
|
-
self.valid_attributes << name
|
207
|
+
self.valid_attributes += [name]
|
176
208
|
|
177
209
|
case type
|
178
210
|
when :datetime
|
@@ -188,6 +220,10 @@ module ActivePodio
|
|
188
220
|
define_boolean_accessors(name)
|
189
221
|
when :array
|
190
222
|
define_array_accessors(name)
|
223
|
+
when :float
|
224
|
+
define_float_accessor(name)
|
225
|
+
when :decimal
|
226
|
+
define_decimal_accessor(name)
|
191
227
|
else
|
192
228
|
define_generic_accessor(name)
|
193
229
|
end
|
@@ -195,8 +231,7 @@ module ActivePodio
|
|
195
231
|
|
196
232
|
# Wraps a single hash provided from the API in the given model
|
197
233
|
def has_one(name, options = {})
|
198
|
-
self._associations
|
199
|
-
self._associations[name] = :has_one
|
234
|
+
self._associations = self._associations.merge({name => :has_one})
|
200
235
|
|
201
236
|
self.send(:define_method, name) do
|
202
237
|
klass = klass_for_association(options)
|
@@ -220,8 +255,7 @@ module ActivePodio
|
|
220
255
|
|
221
256
|
# Wraps a collection of hashes from the API to a collection of the given model
|
222
257
|
def has_many(name, options = {})
|
223
|
-
self._associations
|
224
|
-
self._associations[name] = :has_many
|
258
|
+
self._associations = self._associations.merge({name => :has_many})
|
225
259
|
|
226
260
|
self.send(:define_method, name) do
|
227
261
|
klass = klass_for_association(options)
|
@@ -229,7 +263,7 @@ module ActivePodio
|
|
229
263
|
unless instances.present?
|
230
264
|
property = options[:property] || name.to_sym
|
231
265
|
if self[property].present? && self[property].respond_to?(:map)
|
232
|
-
instances = self[property].map { |attributes| klass.new(attributes) }
|
266
|
+
instances = self[property].map { |attributes| klass.new(attributes, :belongs_to => { :model => self }) }
|
233
267
|
self.instance_variable_set("@#{name}_has_many_instances", instances)
|
234
268
|
else
|
235
269
|
instances = []
|
@@ -284,45 +318,16 @@ module ActivePodio
|
|
284
318
|
end
|
285
319
|
end
|
286
320
|
|
287
|
-
# Wraps the given methods in a begin/rescue block
|
288
|
-
# If no error occurs, the return value of the method, or true if nil is returned, is returned
|
289
|
-
# If a Podio::PodioError occurs, the method returns false and the error can be read from the error_message accessor
|
290
|
-
# If another error occurs, it is still raised
|
291
|
-
def handle_api_errors_for(*method_names)
|
292
|
-
method_names.each do |method_name|
|
293
|
-
self.send(:define_method, "#{method_name}_with_api_errors_handled") do |*args|
|
294
|
-
success, code, message, parameters, result = nil
|
295
|
-
begin
|
296
|
-
result = self.send("#{method_name}_without_api_errors_handled", *args)
|
297
|
-
success = true
|
298
|
-
rescue Podio::PodioError => ex
|
299
|
-
success = false
|
300
|
-
code = ex.response_body["error"]
|
301
|
-
message = ex.response_body["error_description"]
|
302
|
-
parameters = ex.response_body["error_parameters"]
|
303
|
-
propagate = ex.response_body["error_propagate"]
|
304
|
-
end
|
305
|
-
|
306
|
-
if success
|
307
|
-
return result || true
|
308
|
-
else
|
309
|
-
@error_code = code
|
310
|
-
@error_message = message
|
311
|
-
@error_parameters = parameters || {}
|
312
|
-
@error_propagate = propagate
|
313
|
-
return false
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
alias_method_chain method_name, :api_errors_handled
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
321
|
def output_attribute_as_json(*attributes)
|
322
|
-
self.json_attributes ||= []
|
323
322
|
self.json_attributes += attributes
|
324
323
|
end
|
325
324
|
|
325
|
+
def klass_from_string(klass_name)
|
326
|
+
klass = klass_name.constantize rescue nil
|
327
|
+
klass = "Podio::#{klass_name}".constantize unless klass.respond_to?(:ancestors) && klass.ancestors.include?(ActivePodio::Base)
|
328
|
+
return klass
|
329
|
+
end
|
330
|
+
|
326
331
|
private
|
327
332
|
|
328
333
|
def define_generic_accessor(name, options = {})
|
@@ -354,7 +359,11 @@ module ActivePodio
|
|
354
359
|
value = if value.is_a?(DateTime)
|
355
360
|
Time.zone.local_to_utc(value)
|
356
361
|
else
|
357
|
-
|
362
|
+
begin
|
363
|
+
Time.zone.parse(value).try(:utc).try(:to_datetime)
|
364
|
+
rescue TZInfo::AmbiguousTime
|
365
|
+
nil
|
366
|
+
end
|
358
367
|
end
|
359
368
|
end
|
360
369
|
|
@@ -419,6 +428,42 @@ module ActivePodio
|
|
419
428
|
end
|
420
429
|
end
|
421
430
|
|
431
|
+
def define_float_accessor(name)
|
432
|
+
self.send(:define_method, name) do
|
433
|
+
if self[name.to_sym].present?
|
434
|
+
self[name.to_sym].to_f
|
435
|
+
else
|
436
|
+
nil
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
self.send(:define_method, "#{name}=") do |value|
|
441
|
+
if value.present?
|
442
|
+
self[name.to_sym] = value.to_f
|
443
|
+
else
|
444
|
+
self[name.to_sym] = nil
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
def define_decimal_accessor(name)
|
450
|
+
self.send(:define_method, name) do
|
451
|
+
if self[name.to_sym].present?
|
452
|
+
BigDecimal(self[name.to_sym], 2)
|
453
|
+
else
|
454
|
+
nil
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
self.send(:define_method, "#{name}=") do |value|
|
459
|
+
if value.present?
|
460
|
+
self[name.to_sym] = BigDecimal(value, 2)
|
461
|
+
else
|
462
|
+
self[name.to_sym] = nil
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
422
467
|
def define_boolean_accessors(name)
|
423
468
|
self.send(:define_method, "#{name}?") do
|
424
469
|
if self[name.to_sym].present?
|