Class: Xeroizer::Record::BaseModel

Inherits:
Object
  • Object
show all
Includes:
ClassLevelInheritableAttributes, BaseModelHttpProxy
Defined in:
lib/xeroizer/record/base_model.rb

Defined Under Namespace

Modules: InvaidPermissionError Classes: InvalidPermissionError

Constant Summary

ALLOWED_PERMISSIONS =
[:read, :write, :update]
DEFAULT_RECORDS_PER_BATCH_SAVE =
50

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from BaseModelHttpProxy

included

Methods included from ClassLevelInheritableAttributes

included

Constructor Details

#initialize(application, model_name) ⇒ BaseModel



75
76
77
78
# File 'lib/xeroizer/record/base_model.rb', line 75

def initialize(application, model_name)
  @application = application
  @model_name = model_name
end

Instance Attribute Details

#applicationObject (readonly)

Returns the value of attribute application



26
27
28
# File 'lib/xeroizer/record/base_model.rb', line 26

def application
  @application
end

#model_classObject (readonly)

Returns the value of attribute model_class



28
29
30
# File 'lib/xeroizer/record/base_model.rb', line 28

def model_class
  @model_class
end

#model_nameObject (readonly)

Returns the value of attribute model_name



27
28
29
# File 'lib/xeroizer/record/base_model.rb', line 27

def model_name
  @model_name
end

#responseObject (readonly)

Returns the value of attribute response



29
30
31
# File 'lib/xeroizer/record/base_model.rb', line 29

def response
  @response
end

Class Method Details

.set_api_controller_name(controller_name) ⇒ Object

Method to allow override of the default controller name used in the API URLs.

Default: pluaralized model name (e.g. if the controller name is Invoice then the default is Invoices.



38
39
40
# File 'lib/xeroizer/record/base_model.rb', line 38

def set_api_controller_name(controller_name)
  self.api_controller_name = controller_name
end

.set_optional_xml_root_name(optional_root_name) ⇒ Object

Method to add an extra top-level node to use in has_many associations.



67
68
69
# File 'lib/xeroizer/record/base_model.rb', line 67

def set_optional_xml_root_name(optional_root_name)
  self.optional_xml_root_name = optional_root_name
end

.set_permissions(*args) ⇒ Object

Set the permissions allowed for this class type. There are no permissions set by default. Valid permissions are :read, :write, :update.



45
46
47
48
49
50
51
# File 'lib/xeroizer/record/base_model.rb', line 45

def set_permissions(*args)
  self.permissions = {}
  args.each do | permission |
    raise InvalidPermissionError.new("Permission #{permission} is invalid.") unless ALLOWED_PERMISSIONS.include?(permission)
    self.permissions[permission] = true
  end
end

.set_xml_node_name(node_name) ⇒ Object

Method to allow override of the default XML node name.

Default: singularized model name in camel-case.



56
57
58
# File 'lib/xeroizer/record/base_model.rb', line 56

def set_xml_node_name(node_name)
  self.xml_node_name = node_name
end

.set_xml_root_name(root_name) ⇒ Object

Method to allow override of the default XML root name to use in has_many associations.



62
63
64
# File 'lib/xeroizer/record/base_model.rb', line 62

def set_xml_root_name(root_name)
  self.xml_root_name = root_name
end

Instance Method Details

#all(options = {}) ⇒ Object

Retreive full record list for this model.

Raises:



118
119
120
121
122
123
# File 'lib/xeroizer/record/base_model.rb', line 118

def all(options = {})
  raise MethodNotAllowed.new(self, :all) unless self.class.permissions[:read]
  response_xml = http_get(parse_params(options))
  response = parse_response(response_xml, options)
  response.response_items || []
end

#api_controller_nameObject

Retrieve the controller name.

Default: pluaralized model name (e.g. if the controller name is Invoice then the default is Invoices.



84
85
86
# File 'lib/xeroizer/record/base_model.rb', line 84

def api_controller_name
  self.class.api_controller_name || model_name.pluralize
end

#batch_save(chunk_size = DEFAULT_RECORDS_PER_BATCH_SAVE) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/xeroizer/record/base_model.rb', line 166

def batch_save(chunk_size = DEFAULT_RECORDS_PER_BATCH_SAVE)
  @objects = {}
  @allow_batch_operations = true

  begin
    yield

    if @objects[model_class]
      objects = @objects[model_class].values.compact
      save_records(objects, chunk_size)
    end
  ensure
    @objects = {}
    @allow_batch_operations = false
  end
end

#build(attributes = {}) ⇒ Object

Build a record with attributes set to the value of attributes.



93
94
95
96
97
# File 'lib/xeroizer/record/base_model.rb', line 93

def build(attributes = {})
  model_class.build(attributes, self).tap do |resource|
    mark_dirty(resource)
  end
end

#create(attributes = {}) ⇒ Object

Create (build and save) a record with attributes set to the value of attributes.



113
114
115
# File 'lib/xeroizer/record/base_model.rb', line 113

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

#create_methodObject



192
193
194
# File 'lib/xeroizer/record/base_model.rb', line 192

def create_method
  :http_put
end

#find(id, options = {}) ⇒ Object

Retrieve record matching the passed in ID.

Raises:



134
135
136
137
138
139
140
141
# File 'lib/xeroizer/record/base_model.rb', line 134

def find(id, options = {})
  raise MethodNotAllowed.new(self, :all) unless self.class.permissions[:read]
  response_xml = @application.http_get(@application.client, "#{url}/#{CGI.escape(id)}", options)
  response = parse_response(response_xml, options)
  result = response.response_items.first if response.response_items.is_a?(Array)
  result.complete_record_downloaded = true if result
  result
end

#first(options = {}) ⇒ Object

Helper method to retrieve just the first element from the full record list.

Raises:



127
128
129
130
131
# File 'lib/xeroizer/record/base_model.rb', line 127

def first(options = {})
  raise MethodNotAllowed.new(self, :all) unless self.class.permissions[:read]
  result = all(options)
  result.first if result.is_a?(Array)
end

#mark_clean(resource) ⇒ Object



106
107
108
109
110
# File 'lib/xeroizer/record/base_model.rb', line 106

def mark_clean(resource)
  if @objects and @objects[model_class]
    @objects[model_class].delete(resource.object_id)
  end
end

#mark_dirty(resource) ⇒ Object



99
100
101
102
103
104
# File 'lib/xeroizer/record/base_model.rb', line 99

def mark_dirty(resource)
  if @allow_batch_operations
    @objects[model_class] ||= {}
    @objects[model_class][resource.object_id] ||= resource
  end
end

#parse_response(response_xml, options = {}) ⇒ Object



183
184
185
186
187
188
189
190
# File 'lib/xeroizer/record/base_model.rb', line 183

def parse_response(response_xml, options = {})
  Response.parse(response_xml, options) do | response, elements, response_model_name |
    if model_name == response_model_name
      @response = response
      parse_records(response, elements, paged_records_requested?(options))
    end
  end
end

#save_records(records, chunk_size = DEFAULT_RECORDS_PER_BATCH_SAVE) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/xeroizer/record/base_model.rb', line 143

def save_records(records, chunk_size = DEFAULT_RECORDS_PER_BATCH_SAVE)
  no_errors = true
  return false unless records.all?(&:valid?)

  actions = records.group_by {|o| o.new_record? ? create_method : :http_post }
  actions.each_pair do |http_method, records_for_method|
    records_for_method.each_slice(chunk_size) do |some_records|
      request = to_bulk_xml(some_records)
      response = parse_response(self.send(http_method, request, {:summarizeErrors => false}))
      response.response_items.each_with_index do |record, i|
        if record and record.is_a?(model_class)
          some_records[i].attributes = record.non_calculated_attributes
          some_records[i].errors = record.errors
          no_errors = record.errors.nil? || record.errors.empty? if no_errors
          some_records[i].saved!
        end
      end
    end
  end

  no_errors
end