Class: OldApiResource::Base

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Naming
Includes:
Associations, Attributes, Callbacks, ModelErrors
Defined in:
lib/old_api_resource/base.rb,
lib/old_api_resource/base.rb

Constant Summary

Constants included from Associations

Associations::ASSOCIATION_TYPES

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}) ⇒ Base

Returns a new instance of Base.



334
335
336
337
# File 'lib/old_api_resource/base.rb', line 334

def initialize(attributes = {})
  @prefix_options = {}
  load(attributes)
end

Class Attribute Details

.collection_nameObject

collection_name with default



162
163
164
# File 'lib/old_api_resource/base.rb', line 162

def collection_name
  @collection_name ||= ActiveSupport::Inflector.pluralize(self.element_name)
end

.element_nameObject

element_name with default



158
159
160
# File 'lib/old_api_resource/base.rb', line 158

def element_name
  @element_name ||= self.model_name.element
end

Instance Attribute Details

#prefix_optionsObject

Returns the value of attribute prefix_options.



17
18
19
# File 'lib/old_api_resource/base.rb', line 17

def prefix_options
  @prefix_options
end

Class Method Details

.all(*args) ⇒ Object

This is an alias for find(:all). You can pass in all the same arguments to this method as you can to find(:all)



222
223
224
# File 'lib/old_api_resource/base.rb', line 222

def all(*args)
  find(:all, *args)
end

.build(attributes = {}) ⇒ Object



184
185
186
# File 'lib/old_api_resource/base.rb', line 184

def build(attributes = {})
  self.new(attributes)
end

.collection_path(prefix_options = {}, query_options = nil) ⇒ Object



179
180
181
182
# File 'lib/old_api_resource/base.rb', line 179

def collection_path(prefix_options = {}, query_options = nil)
  prefix_options, query_options = split_options(prefix_options) if query_options.nil?
  "#{prefix(prefix_options)}#{collection_name}.#{format.extension}#{query_string(query_options)}"
end

.connection(refresh = false) ⇒ Object



121
122
123
124
125
# File 'lib/old_api_resource/base.rb', line 121

def connection(refresh = false)
  @connection = Connection.new(self.site, self.format) if refresh || @connection.nil?
  @connection.timeout = self.timeout
  @connection
end

.create(attributes = {}) ⇒ Object



188
189
190
# File 'lib/old_api_resource/base.rb', line 188

def create(attributes = {})
  self.new(attributes).tap{ |resource| resource.save }
end

.delete(id, options = {}) ⇒ Object

Deletes the resources with the ID in the id parameter.

Options

All options specify prefix and query parameters.

Examples

Event.delete(2) # sends DELETE /events/2

Event.create(:name => 'Free Concert', :location => 'Community Center')
my_event = Event.find(:first) # let's assume this is event with ID 7
Event.delete(my_event.id) # sends DELETE /events/7

# Let's assume a request to events/5/cancel.xml
Event.delete(params[:id]) # sends DELETE /events/5


241
242
243
# File 'lib/old_api_resource/base.rb', line 241

def delete(id, options = {})
  connection.delete(element_path(id, options))
end

.element_path(id, prefix_options = {}, query_options = nil) ⇒ Object

alias_method :set_prefix, :prefix= alias_method :set_element_name, :element_name= alias_method :set_collection_name, :collection_name=



170
171
172
173
# File 'lib/old_api_resource/base.rb', line 170

def element_path(id, prefix_options = {}, query_options = nil)
  prefix_options, query_options = split_options(prefix_options) if query_options.nil?
  "#{prefix(prefix_options)}#{collection_name}/#{URI.escape id.to_s}.#{format.extension}#{query_string(query_options)}"
end

.find(*arguments) ⇒ Object



192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/old_api_resource/base.rb', line 192

def find(*arguments)
  scope   = arguments.slice!(0)
  options = arguments.slice!(0) || {}

  case scope
    when :all   then find_every(options)
    when :first then find_every(options).first
    when :last  then find_every(options).last
    when :one   then find_one(options)
    else             find_single(scope, options)
  end
end

.first(*args) ⇒ Object

A convenience wrapper for find(:first, *args). You can pass in all the same arguments to this method as you can to find(:first).



209
210
211
# File 'lib/old_api_resource/base.rb', line 209

def first(*args)
  find(:first, *args)
end

.formatObject

Default format is json



112
113
114
# File 'lib/old_api_resource/base.rb', line 112

def format
  read_inheritable_attribute(:format) || OldApiResource::Formats::JsonFormat
end

.format=(mime_type_or_format) ⇒ Object



105
106
107
108
109
# File 'lib/old_api_resource/base.rb', line 105

def format=(mime_type_or_format)
  format = mime_type_or_format.is_a?(Symbol) ? OldApiResource::Formats[mime_type_or_format] : mime_type_or_format
  write_inheritable_attribute(:format, format)
  self.connection.format = format if self.site
end

.headersObject



127
128
129
# File 'lib/old_api_resource/base.rb', line 127

def headers
  @headers || {}
end

.inherited(klass) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/old_api_resource/base.rb', line 24

def inherited(klass)
  # Call the methods of the superclass to make sure inheritable accessors and the like have been inherited
  super
  # Now we need to define the inherited method on the klass that's doing the inheriting
  # it calls super which will allow the chaining effect we need
  klass.instance_eval <<-EOE, __FILE__, __LINE__ + 1
    def inherited(klass)
      super
    end
  EOE
  # Now we can make a call to setup the inheriting klass with its attributes
  klass.set_class_attributes_upon_load unless klass.instance_variable_defined?(:@class_data)
  klass.instance_variable_set(:@class_data, true)
  # we want to reset element_name and collection_name for the inherited class
  true
end

.last(*args) ⇒ Object

A convenience wrapper for find(:last, *args). You can pass in all the same arguments to this method as you can to find(:last).



216
217
218
# File 'lib/old_api_resource/base.rb', line 216

def last(*args)
  find(:last, *args)
end

.new_element_path(prefix_options = {}) ⇒ Object



175
176
177
# File 'lib/old_api_resource/base.rb', line 175

def new_element_path(prefix_options = {})
  "#{prefix(prefix_options)}#{collection_name}/new.#{format.extension}"
end

.prefix(options = {}) ⇒ Object



131
132
133
134
135
136
# File 'lib/old_api_resource/base.rb', line 131

def prefix(options = {})
  default = (self.site ? self.site.path : '/')
  default << '/' unless default[-1..-1] == '/'
  self.prefix = default
  prefix(options)
end

.prefix=(value = '/') ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/old_api_resource/base.rb', line 143

def prefix=(value = '/')
  prefix_call = value.gsub(/:\w+/) { |key| "\#{URI.escape options[#{key}].to_s}"}
  @prefix_parameters = nil
  silence_warnings do
    instance_eval <<-EOE, __FILE__, __LINE__ + 1
      def prefix_source() "#{value}" end
      def prefix(options={}) "#{prefix_call}" end
    EOE
  end
rescue Exception => e
  logger.error "Couldn't set prefix: #{e}\n #{code}" if logger
  raise
end

.prefix_sourceObject



138
139
140
141
# File 'lib/old_api_resource/base.rb', line 138

def prefix_source
  prefix
  prefix_source
end

.reload_class_attributesObject



76
77
78
79
80
81
# File 'lib/old_api_resource/base.rb', line 76

def reload_class_attributes
  # clear the public_attribute_names, protected_attribute_names
  self.clear_attributes
  self.clear_associations
  self.set_class_attributes_upon_load
end

.set_class_attributes_upon_loadObject

This makes a request to new_element_path



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/old_api_resource/base.rb', line 43

def set_class_attributes_upon_load
  begin
    class_data = self.connection.get(self.new_element_path)
    # Attributes go first
    if class_data["attributes"]
      define_attributes *(class_data["attributes"]["public"] || [])
      define_protected_attributes *(class_data["attributes"]["protected"] || [])
    end
    # Then scopes
    if class_data["scopes"]
      class_data["scopes"].each do |hash|
        self.scope hash.first[0], hash.first[1]
      end
    end
    # Then associations
    if class_data["associations"]
      class_data["associations"].each do |(key,hash)|
        hash.each do |assoc_name, assoc_options|
          self.send(key, assoc_name, assoc_options)
        end
      end
    end
  # Swallow up any loading errors because the site may be incorrect
  rescue Exception => e
    if OldApiResource.raise_missing_definition_error
      raise e 
    end
    OldApiResource.logger.warn("#{self}: #{e.message}")
    OldApiResource.logger.debug(e.backtrace.pretty_inspect)
    return e.respond_to?(:request) ? e.request : nil
  end
end

.site=(site) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/old_api_resource/base.rb', line 83

def site=(site)
  # store so we can reload attributes if the site changed
  old_site = self.site.to_s.clone
  @connection = nil
  
  if site.nil?
    write_inheritable_attribute(:site, nil)
    # no site, so we'll skip the reload
    return site
  else
    write_inheritable_attribute(:site, create_site_uri_from(site))
  end
  
  # reset class attributes and try to reload them if the site changed
  unless self.site.to_s == old_site
    self.reload_class_attributes
  end
  
  return site
end

.timeout=(timeout) ⇒ Object



116
117
118
119
# File 'lib/old_api_resource/base.rb', line 116

def timeout=(timeout)
  @connection = nil
  write_inheritable_attribute(:timeout, timeout)
end

Instance Method Details

#==(other) ⇒ Object



357
358
359
# File 'lib/old_api_resource/base.rb', line 357

def ==(other)
  other.equal?(self) || (other.instance_of?(self.class) && other.id == self.id && other.prefix_options == self.prefix_options)
end

#destroyObject



389
390
391
# File 'lib/old_api_resource/base.rb', line 389

def destroy
  connection.delete(element_path(self.id), self.class.headers)
end

#dupObject



369
370
371
372
373
374
# File 'lib/old_api_resource/base.rb', line 369

def dup
  self.class.new.tap do |resource|
    resource.attributes = self.attributes
    resource.prefix_options = @prefix_options
  end
end

#encode(options = {}) ⇒ Object



393
394
395
# File 'lib/old_api_resource/base.rb', line 393

def encode(options = {})
  self.send("to_#{self.class.format.extension}", options)
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


361
362
363
# File 'lib/old_api_resource/base.rb', line 361

def eql?(other)
  self == other
end

#hashObject



365
366
367
# File 'lib/old_api_resource/base.rb', line 365

def hash
  id.hash
end

#idObject



348
349
350
# File 'lib/old_api_resource/base.rb', line 348

def id
  self.attributes[self.class.primary_key]
end

#id=(id) ⇒ Object

Bypass dirty tracking for this field



353
354
355
# File 'lib/old_api_resource/base.rb', line 353

def id=(id)
  attributes[self.class.primary_key] = id
end

#load(attributes) ⇒ Object

Raises:

  • (ArgumentError)


401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/old_api_resource/base.rb', line 401

def load(attributes)
  return if attributes.nil?
  raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
  @prefix_options, attributes = split_options(attributes)
 
  attributes.symbolize_keys.each do |key, value|
    # If this attribute doesn't exist define it as a protected attribute
    self.class.define_protected_attributes(key) unless self.respond_to?(key)
    self.attributes[key] =
    case value
      when Array
        if self.has_many?(key)
          MultiObjectProxy.new(self.has_many_class_name(key), value)
        elsif self.association?(key)
          raise ArgumentError, "Expected a hash value or nil, got: #{value.inspect}"
        else
          value.dup rescue value
        end
      when Hash
        if self.has_many?(key)
          MultiObjectProxy.new(self.has_many_class_name(key), value)
        elsif self.association?(key)
          SingleObjectProxy.new(self.association_class_name(key), value)
        else
          value.dup rescue value
        end
      when NilClass
        # If it's nil and an association then create a blank object
        if self.has_many?(key)
          return MultiObjectProxy.new(self.has_many_class_name(key), [])
        elsif self.association?(key)
          SingleObjectProxy.new(self.association_class_name(key), value)
        end
      else
        raise ArgumentError, "expected an array or a hash for the association #{key}, got: #{value.inspect}" if self.association?(key)
        value.dup rescue value
    end
  end
  return self
end

#new?Boolean Also known as: new_record?

Returns:

  • (Boolean)


339
340
341
# File 'lib/old_api_resource/base.rb', line 339

def new?
  id.nil?
end

#persisted?Boolean

Returns:

  • (Boolean)


344
345
346
# File 'lib/old_api_resource/base.rb', line 344

def persisted?
  !new?
end

#reloadObject



397
398
399
# File 'lib/old_api_resource/base.rb', line 397

def reload
  self.load(self.class.find(to_param, :params => @prefix_options).attributes)
end

#save(*args) ⇒ Object



381
382
383
# File 'lib/old_api_resource/base.rb', line 381

def save(*args)
  new? ? create(*args) : update(*args)
end

#save!(*args) ⇒ Object



385
386
387
# File 'lib/old_api_resource/base.rb', line 385

def save!(*args)
  save(*args) || raise(OldApiResource::ResourceInvalid.new(self))
end

#serializable_hash(options = {}) ⇒ Object



461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
# File 'lib/old_api_resource/base.rb', line 461

def serializable_hash(options = {})
  options[:include_associations] = options[:include_associations] ? options[:include_associations].symbolize_array : []
  options[:include_extras] = options[:include_extras] ? options[:include_extras].symbolize_array : []
  options[:except] ||= []
  ret = self.attributes.inject({}) do |accum, (key,val)|
    # If this is an association and it's in include_associations then include it
    if self.association?(key) && options[:include_associations].include?(key.to_sym)
      accum.merge(key => val.serializable_hash({:include_id => true}))
    elsif options[:include_extras].include?(key.to_sym)
      accum.merge(key => val)
    elsif options[:except].include?(key.to_sym)
      accum
    else
      self.association?(key) || !self.attribute?(key) || self.protected_attribute?(key) ? accum : accum.merge(key => val)
    end
  end
  # include id - this is for nested updates
  ret[:id] = self.id if options[:include_id] && !self.id.nil?
  ret
end

#to_json(options = {}) ⇒ Object



457
458
459
# File 'lib/old_api_resource/base.rb', line 457

def to_json(options = {})
  self.class.include_root_in_json ? {self.class.element_name => self.serializable_hash(options)}.to_json : self.serializable_hash(options).to_json
end

#to_sObject Also known as: inspect

Override to_s and inspect so they only show attributes and not associations, this prevents force loading of associations when we call to_s or inspect on a descendent of base but allows it if we try to evaluate an association directly



446
447
448
# File 'lib/old_api_resource/base.rb', line 446

def to_s
  return "#<#{self.class}:0x%08x @attributes=#{self.attributes.inject({}){|accum,(k,v)| self.association?(k) ? accum : accum.merge(k => v)}}" % (self.object_id * 2)
end

#to_xml(options = {}) ⇒ Object

Methods for serialization as json or xml, relying on the serializable_hash method



453
454
455
# File 'lib/old_api_resource/base.rb', line 453

def to_xml(options = {})
  self.serializable_hash(options).to_xml(:root => self.class.element_name)
end

#update_attributes(attrs) ⇒ Object



376
377
378
379
# File 'lib/old_api_resource/base.rb', line 376

def update_attributes(attrs)
  self.attributes = attrs
  self.save
end