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
# File 'lib/podio/active_podio/base.rb', line 13

def initialize(attributes = {}, options = {})
  self.valid_attributes ||= []
  attributes = {} if attributes.blank?
  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

  self.initialize_attributes(attributes)

  @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



261
262
263
264
265
# File 'lib/podio/active_podio/base.rb', line 261

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



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/podio/active_podio/base.rb', line 267

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



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/podio/active_podio/base.rb', line 291

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



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/podio/active_podio/base.rb', line 222

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? && self[property].respond_to?(:map)
        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



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/podio/active_podio/base.rb', line 197

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



252
253
254
255
# File 'lib/podio/active_podio/base.rb', line 252

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

.member(response) ⇒ Object

Returns a single instance of the model



247
248
249
# File 'lib/podio/active_podio/base.rb', line 247

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

.output_attribute_as_json(*attributes) ⇒ Object



321
322
323
324
# File 'lib/podio/active_podio/base.rb', line 321

def output_attribute_as_json(*attributes)
  self.json_attributes ||= []
  self.json_attributes += attributes
end

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

Defines the the supported attributes of the model



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/podio/active_podio/base.rb', line 173

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 :time
    define_time_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?



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

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

#[](attribute) ⇒ Object



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

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

#[]=(attribute, value) ⇒ Object



68
69
70
71
72
73
74
75
# File 'lib/podio/active_podio/base.rb', line 68

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



122
123
124
# File 'lib/podio/active_podio/base.rb', line 122

def api_friendly_ref_type
  self.class.name.downcase
end

#as_json(options = {}) ⇒ Object



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
115
116
117
118
119
# File 'lib/podio/active_podio/base.rb', line 86

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

  if options[:formatted]
    (self.valid_attributes + (self.json_attributes || [])).uniq.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



82
83
84
# File 'lib/podio/active_podio/base.rb', line 82

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

#initialize_attributes(attributes) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/podio/active_podio/base.rb', line 26

def initialize_attributes(attributes)
  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) || self.send(key.to_sym).nil?)
      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
          self.send(:[]=, key.to_sym, value) if self.send(key.to_sym).nil? # If not set by constructor, set here to get typed values back
          attributes = self.send(key.to_sym).try(:attributes)
          if attributes.present? && any_values_present_recursive?(attributes.values)
            value = attributes
          else
            value = nil
          end
        end
        self.send(:[]=, key.to_sym, value)
      end
    end
  end
end

#new_record?Boolean

Returns:

  • (Boolean)


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

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

#persisted?Boolean

Returns:

  • (Boolean)


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

def persisted?
  ! self.new_record?
end

#to_paramObject



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

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