Class: ActivePodio::Base

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Callbacks, ActiveModel::Naming
Includes:
ActiveModel::Conversion
Defined in:
lib/podio/active_podio/base.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}, options = {}) ⇒ Base

Returns a new instance of Base.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/podio/active_podio/base.rb', line 13

def initialize(attributes = {}, options = {})
  self.valid_attributes ||= []
  attributes ||= {}
  self.attributes = Hash[*self.valid_attributes.collect { |n| [n.to_sym, nil] }.flatten].merge(attributes.symbolize_keys)

  @values_from_api = options[:values_from_api] # Used to determine if date times should be converted from local to utc, or are already utc

  attributes.each do |key, value|
    if self.respond_to?("#{key}=".to_sym)
      self.send("#{key}=".to_sym, value)
    else
      is_association_hash = value.is_a?(Hash) && self._associations.present? && self._associations.has_key?(key.to_sym) && self._associations[key.to_sym] == :has_one && self.send(key.to_sym).respond_to?(:attributes)
      if valid_attributes.include?(key.to_sym) || is_association_hash
        # Initialize nested object to get correctly casted values set back, unless the given values are all blank
        if is_association_hash
          attributes = self.send(key.to_sym).attributes
          if any_values_present_recursive?(attributes.values)
            value = attributes
          else
            value = nil
          end
        end
        self.send(:[]=, key.to_sym, value)
      end
    end
  end

  @belongs_to = options[:belongs_to] # Allows has_one associations to communicate their changed content back to their parent model
  @values_from_api = false
end

Instance Attribute Details

#attributesObject

Returns the value of attribute attributes.



10
11
12
# File 'lib/podio/active_podio/base.rb', line 10

def attributes
  @attributes
end

#error_codeObject

Returns the value of attribute error_code.



10
11
12
# File 'lib/podio/active_podio/base.rb', line 10

def error_code
  @error_code
end

#error_messageObject

Returns the value of attribute error_message.



10
11
12
# File 'lib/podio/active_podio/base.rb', line 10

def error_message
  @error_message
end

#error_parametersObject

Returns the value of attribute error_parameters.



10
11
12
# File 'lib/podio/active_podio/base.rb', line 10

def error_parameters
  @error_parameters
end

#error_propagateObject Also known as: propagate_error?

Returns the value of attribute error_propagate.



10
11
12
# File 'lib/podio/active_podio/base.rb', line 10

def error_propagate
  @error_propagate
end

Class Method Details

.collection(response) ⇒ Object

Returns a struct that includes:

  • all: A collection model instances

  • count: The number of returned records

  • total_count: The total number of records matching the given conditions



249
250
251
252
253
# File 'lib/podio/active_podio/base.rb', line 249

def collection(response)
  result = Struct.new(:all, :count, :total_count).new(response['items'], response['filtered'], response['total'])
  result.all.map! { |item| new(item, :values_from_api => true) }
  result
end

.delegate_to_hash(hash_name, *attribute_names) ⇒ Object



255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/podio/active_podio/base.rb', line 255

def delegate_to_hash(hash_name, *attribute_names)
  options = attribute_names.extract_options!
  options.reverse_merge!(:prefix => false, :setter => false)
  options.assert_valid_keys(:prefix, :setter)
  attribute_names.each do |attribute_name|
    hash_index = attribute_name.to_s.gsub(/[\?!]/, '')
    method_name = "#{options[:prefix] ? "#{hash_name}_" : ''}#{attribute_name}"
    self.send(:define_method, method_name) do
      self.send("#{hash_name}=", {}) unless self.send(hash_name)
      self.send(hash_name)[hash_index]
    end
    if options[:setter]
      self.send(:define_method, "#{method_name}=") do |value|
        self.send("#{hash_name}=", {}) unless self.send(hash_name)
        self.send(hash_name)[hash_index] = value
      end
    end
  end
end

.handle_api_errors_for(*method_names) ⇒ Object

Wraps the given methods in a begin/rescue block If no error occurs, the return value of the method, or true if nil is returned, is returned If a Podio::PodioError occurs, the method returns false and the error can be read from the error_message accessor If another error occurs, it is still raised



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/podio/active_podio/base.rb', line 279

def handle_api_errors_for(*method_names)
  method_names.each do |method_name|
    self.send(:define_method, "#{method_name}_with_api_errors_handled") do |*args|
      success, code, message, parameters, result = nil
      begin
        result = self.send("#{method_name}_without_api_errors_handled", *args)
        success = true
      rescue Podio::PodioError => ex
        success = false
        code        = ex.response_body["error"]
        message     = ex.response_body["error_description"]
        parameters  = ex.response_body["error_parameters"]
        propagate  = ex.response_body["error_propagate"]
      end

      if success
        return result || true
      else
        @error_code       = code
        @error_message    = message
        @error_parameters = parameters || {}
        @error_propagate  = propagate
        return false
      end
    end

    alias_method_chain method_name, :api_errors_handled
  end
end

.has_many(name, options = {}) ⇒ Object

Wraps a collection of hashes from the API to a collection of the given model



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/podio/active_podio/base.rb', line 210

def has_many(name, options = {})
  self._associations ||= {}
  self._associations[name] = :has_many

  self.send(:define_method, name) do
    klass = klass_for_association(options)
    instances = self.instance_variable_get("@#{name}_has_many_instances")
    unless instances.present?
      property = options[:property] || name.to_sym
      if self[property].present?
        instances = self[property].map { |attributes| klass.new(attributes) }
        self.instance_variable_set("@#{name}_has_many_instances", instances)
      else
        instances = []
      end
    end
    instances
  end

  self.send(:define_method, "#{name}?") do
    self.send(name).length > 0
  end
end

.has_one(name, options = {}) ⇒ Object

Wraps a single hash provided from the API in the given model



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/podio/active_podio/base.rb', line 185

def has_one(name, options = {})
  self._associations ||= {}
  self._associations[name] = :has_one

  self.send(:define_method, name) do
    klass = klass_for_association(options)
    instance = self.instance_variable_get("@#{name}_has_one_instance")
    unless instance.present?
      property = options[:property] || name.to_sym
      if self[property].present?
        instance = klass.new(self[property], :belongs_to => { :model => self, :as => property })
        self.instance_variable_set("@#{name}_has_one_instance", instance)
      else
        instance = nil
      end
    end
    instance
  end

  self.send(:define_method, "clear_#{name}") do
    self.instance_variable_set("@#{name}_has_one_instance", nil)
  end
end

.list(response) ⇒ Object

Returns a simple collection model instances



240
241
242
243
# File 'lib/podio/active_podio/base.rb', line 240

def list(response)
  response.map! { |item| new(item, :values_from_api => true) }
  response
end

.member(response) ⇒ Object

Returns a single instance of the model



235
236
237
# File 'lib/podio/active_podio/base.rb', line 235

def member(response)
  new(response, :values_from_api => true)
end

.property(name, type = :string, options = {}) ⇒ Object

Defines the the supported attributes of the model



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/podio/active_podio/base.rb', line 163

def property(name, type = :string, options = {})
  self.valid_attributes ||= []
  self.valid_attributes << name

  case type
  when :datetime
    define_datetime_accessor(name, options)
  when :date
    define_date_accessor(name)
  when :integer
    define_integer_accessor(name)
  when :boolean
    define_generic_accessor(name, :setter => false)
    define_boolean_accessors(name)
  when :array
    define_array_accessors(name)
  else
    define_generic_accessor(name)
  end
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



72
73
74
# File 'lib/podio/active_podio/base.rb', line 72

def ==(other)
  !self.nil? && !other.nil? && self.respond_to?(:id) && other.respond_to?(:id) && self.id == other.id
end

#[](attribute) ⇒ Object



58
59
60
61
# File 'lib/podio/active_podio/base.rb', line 58

def [](attribute)
  @attributes ||= {}
  @attributes[attribute.to_sym]
end

#[]=(attribute, value) ⇒ Object



63
64
65
66
67
68
69
70
# File 'lib/podio/active_podio/base.rb', line 63

def []=(attribute, value)
  @attributes ||= {}
  @attributes[attribute.to_sym] = value
  if @belongs_to.present? && value.present?
    @belongs_to[:model][@belongs_to[:as]] ||= {}
    @belongs_to[:model][@belongs_to[:as]][attribute.to_sym] = value
  end
end

#api_friendly_ref_typeObject

Override this in models where the class name doesn’t match the ref type



117
118
119
# File 'lib/podio/active_podio/base.rb', line 117

def api_friendly_ref_type
  self.class.name.downcase
end

#as_json(options = {}) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/podio/active_podio/base.rb', line 81

def as_json(options={})
  options ||= {}
  result = {}
  result.merge!(:id => self.id) if self.respond_to?(:id)

  if options[:formatted]
    self.valid_attributes.each do |name|
      result[name] = json_friendly_value(self.send(name), options)
    end

    unless options[:nested] == false
      if self._associations.respond_to?(:each)
        self._associations.each do |name, type|
          case type
          when :has_one
            result[name] = self.send(name).as_json(options.except(:methods))
          when :has_many
            result[name] = self.send(name).collect { |assoc| assoc.as_json(options.except(:methods)) }
          end
        end
      end
    end
  else
    result.merge!(self.attributes)
  end

  if options[:methods]
    options[:methods].each do |name|
      result[name] = json_friendly_value(self.send(name), options)
    end
  end

  result
end

#hashObject



77
78
79
# File 'lib/podio/active_podio/base.rb', line 77

def hash
  self.id.hash if self.respond_to?(:id)
end

#new_record?Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/podio/active_podio/base.rb', line 48

def new_record?
  ! (self.respond_to?(:id) && self.id.present?)
end

#persisted?Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/podio/active_podio/base.rb', line 44

def persisted?
  ! self.new_record?
end

#to_paramObject



52
53
54
55
56
# File 'lib/podio/active_podio/base.rb', line 52

def to_param
  local_id = self.id if self.respond_to?(:id)
  local_id = nil if local_id == self.object_id # Id still returns object_id in Ruby 1.8.7, JRuby and Rubinius
  local_id.try(:to_s)
end