Class: Quickbooks::Base
Overview
Base is just base for ListItem and Transaction. It inherits from Model, just as Ref does.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#response_log ⇒ Object
:nodoc:.
Class Method Summary collapse
-
.all(filters = {}) ⇒ Object
Queries Quickbooks for all of the objects of the current class’s type.
-
.connection ⇒ Object
Returns the current Connection.
-
.connection=(conn) ⇒ Object
Sets the current Connection.
-
.create(*args) ⇒ Object
Creates a new object of the current class’s type.
-
.establish_connection(*args) ⇒ Object
Establishes a connection to the Quickbooks RDS Server for all Model Classes.
-
.first(filters = {}) ⇒ Object
Queries Quickbooks for the first object of the current class’s type.
-
.instantiate(obj_or_attrs = {}, attrs = {}) ⇒ Object
Instantiate a new object with just attributes, or an existing object replacing the attributes.
-
.query(obj_or_args, *args) ⇒ Object
Generates a request by sending *args to Qbxml::Request.new, sends the request over the current connection, and interprets the response using Qbxml::ResponseSet.
-
.request(*args) ⇒ Object
Generates a request using Qbxml::Request, sends it, and returns a Qbxml::ResponseSet object containing the response(s).
- .use_adapter(adapter) ⇒ Object
Instance Method Summary collapse
-
#==(other) ⇒ Object
Usual comparison (super), but add in false if either is a new record.
-
#destroy ⇒ Object
Destroys a record in Quickbooks.
-
#initialize(*args) ⇒ Base
constructor
A new instance of Base.
-
#inspect ⇒ Object
:nodoc:.
-
#new_record? ⇒ Boolean
Returns true if the object is a new object (that doesn’t represent an existing object in Quickbooks).
-
#reload ⇒ Object
Reloads the record from Quickbooks, discarding any changes that have been made to it.
-
#save ⇒ Object
Saves the attributes that have changed.
-
#success? ⇒ Boolean
Returns success (true/false) status of the last quickbooks communication called from this object.
Methods inherited from Model
#===, #attributes, #attributes=, camelized_valid_filters, #dirty?, #dirty_attributes, filter_aliases, filter_aliases=, inherited, #original_values, properties, read_only, read_write, #to_dirty_hash, #to_hash, valid_filters, valid_filters=
Constructor Details
#initialize(*args) ⇒ Base
Returns a new instance of Base.
186 187 188 189 |
# File 'lib/quickbooks/base.rb', line 186 def initialize(*args) super # from Quickbooks::Model - sets the *args into attributes @new_record = true end |
Instance Attribute Details
#response_log ⇒ Object
:nodoc:
80 81 82 |
# File 'lib/quickbooks/base.rb', line 80 def response_log @response_log end |
Class Method Details
.all(filters = {}) ⇒ Object
Queries Quickbooks for all of the objects of the current class’s type. For example, Quickbooks::Customer.all will return an array of Quickbooks::Customer objects representing all customers.
169 170 171 172 |
# File 'lib/quickbooks/base.rb', line 169 def all(filters={}) filters.reverse_merge!(:active_status => 'All') [query(self, :query, filters)].flatten end |
.connection ⇒ Object
Returns the current Connection
107 108 109 |
# File 'lib/quickbooks/base.rb', line 107 def connection @connection || (@@connection ||= self.establish_connection()) end |
.connection=(conn) ⇒ Object
Sets the current Connection.
This is normally not needed, but in the case that you may want to connect a separate connection to Quickbooks, you can use this method to explicitly set the connection in a class that inherits from Quickbooks::Base.
Quickbooks::Models::Base.connection = Quickbooks::Connection.new('My Test App', 'C:\\Some File.QBW', 'user', 'pass')
116 117 118 119 |
# File 'lib/quickbooks/base.rb', line 116 def connection=(conn) raise ArgumentError, "Cannot set connection to anything but a (*)Adapter::Connection object" unless conn.class.name =~ /Adapter::Connection$/ @connection = conn end |
.create(*args) ⇒ Object
Creates a new object of the current class’s type. For example, Quickbooks::Customer.create(:name => ‘Tommy’) will create a customer object with a Name of Tommy.
181 182 183 |
# File 'lib/quickbooks/base.rb', line 181 def create(*args) new(*args).save end |
.establish_connection(*args) ⇒ Object
Establishes a connection to the Quickbooks RDS Server for all Model Classes
101 102 103 104 |
# File 'lib/quickbooks/base.rb', line 101 def establish_connection(*args) @@connection_adapter ||= use_adapter(:ole) @@connection = @@connection_adapter.new(*args) end |
.first(filters = {}) ⇒ Object
Queries Quickbooks for the first object of the current class’s type. For example, Quickbooks::Customer.first will return a Quickbooks::Customer object representing the first customer.
175 176 177 178 |
# File 'lib/quickbooks/base.rb', line 175 def first(filters={}) (filters.merge!(:max_returned => 1) unless filters.keys.include?(:list_id) || filters.keys.include?(:txn_id) || filters.keys.include?(:full_name)) if filters.is_a?(Hash) query(self, :query, filters) end |
.instantiate(obj_or_attrs = {}, attrs = {}) ⇒ Object
Instantiate a new object with just attributes, or an existing object replacing the attributes
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/quickbooks/base.rb', line 152 def instantiate(obj_or_attrs={},attrs={}) if obj_or_attrs.is_a?(Quickbooks::Base) obj = obj_or_attrs else obj = allocate attrs = obj_or_attrs end attrs.each do |key,value| if obj.respond_to?(key.to_s.underscore+'=') obj.send(key.to_s.underscore+'=', value) obj.original_values[key.to_s.underscore] = obj.instance_variable_get('@' + key.to_s.underscore).dup end end if attrs obj # Will be either a nice object, or a Qbxml::Error object. end |
.query(obj_or_args, *args) ⇒ Object
Generates a request by sending *args to Qbxml::Request.new, sends the request over the current connection, and interprets the response using Qbxml::ResponseSet. The response is then instantiated into an object or an array of objects.
This method is used mostly internally, but it is the yoke of this library - use it to perform custom requests.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/quickbooks/base.rb', line 126 def query(obj_or_args,*args) # If an object is sent, we need to reinstantiate the response into that object reinstantiate = if obj_or_args.is_a?(Quickbooks::Base) obj_or_args elsif obj_or_args.is_a?(Class) nil else args.unshift(obj_or_args) nil end objects = [] # This will hold and return the instantiated objects from the quickbooks response # The following is subject to bugginess, IF the response contains more than one object: it will instantiate only the last one. self.request(reinstantiate || self, *args).each { |response| objects << response.instantiate(reinstantiate) } # Does not instantiate if it's an error, but simply records response into response_log objects.length == 1 ? objects[0] : objects end |
.request(*args) ⇒ Object
Generates a request using Qbxml::Request, sends it, and returns a Qbxml::ResponseSet object containing the response(s).
143 144 145 146 147 148 149 |
# File 'lib/quickbooks/base.rb', line 143 def request(*args) Qbxml::ResponseSet.new( self.connection.send_xml( Qbxml::Request.new(*args).to_xml ) ) end |
.use_adapter(adapter) ⇒ Object
94 95 96 97 98 |
# File 'lib/quickbooks/base.rb', line 94 def use_adapter(adapter) # Should complain if the adapter doesn't exist. require "#{File.dirname(__FILE__)}/adapters/#{adapter.to_s}_adapter" @@connection_adapter = Object.module_eval("::Quickbooks::#{adapter.to_s.camelize}Adapter::Connection", __FILE__, __LINE__) end |
Instance Method Details
#==(other) ⇒ Object
Usual comparison (super), but add in false if either is a new record.
244 245 246 247 248 |
# File 'lib/quickbooks/base.rb', line 244 def ==(other) return false unless other.is_a?(self.class) return false if self.new_record? || other.new_record? super end |
#destroy ⇒ Object
Destroys a record in Quickbooks. Note that even though Quickbooks will destroy the record, the record’s ListID and DeletedTime can be accessed by doing a query for deleted objects of the appropriate type.
239 240 241 |
# File 'lib/quickbooks/base.rb', line 239 def destroy self.class.query(self, :delete).success? end |
#inspect ⇒ Object
:nodoc:
89 90 91 |
# File 'lib/quickbooks/base.rb', line 89 def inspect #:nodoc: "#<#{self.class.name}:#{self.object_id} #{instance_variables.reject {|i| i.is_one_of?('@response_log', '@original_values')}.map {|i| "#{i}=#{instance_variable_get(i).inspect}"}.join(' ')}>" end |
#new_record? ⇒ Boolean
Returns true if the object is a new object (that doesn’t represent an existing object in Quickbooks).
192 193 194 |
# File 'lib/quickbooks/base.rb', line 192 def new_record? @new_record end |
#reload ⇒ Object
Reloads the record from Quickbooks, discarding any changes that have been made to it.
233 234 235 |
# File 'lib/quickbooks/base.rb', line 233 def reload self.class.query(self, :query) end |
#save ⇒ Object
Saves the attributes that have changed.
If the EditSequence is out of date but none of the changes conflict, the object will be saved to Quickbooks. But if there are conflicts, the updated values from Quickbooks will be written to the original_values, and false is returned. This way you can deal with the differences (conflicts), if you so desire, and simply call save again to commit your changes.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/quickbooks/base.rb', line 201 def save return false unless dirty? self.errors.clear # Clear out any errors: start with a clean slate! if new_record? self.class.query(self, :add) ret = !dirty? @new_record = false if ret else # Smart system that respects EditSequences and other people's changes. # 1) Try to save # 2) When we get a status of 3200, that means our EditSequence is not up to date # 3) Replace self's original_attributes with those just retrieved, and update the automatic attributes, like EditSequence and TimeModified # 4) Return false, return the object dirty but ready to save old_originals = original_values.dup # Save the old_originals so we can detect any attributes that changed since we last loaded the object ret = self.class.query(self, :mod).error? ? false : true # Saves if possible, if EditSequence is out of date, it will read the up-to-date object into original_values # If save failed (dirty?) because of old record (status 3200), but none of the fields conflict (attributes I've modified and are still different aren't the same attributes as any of the attributes someone else updated), then re-save! if dirty? && self.response_log.last.status == 3200 && (dirty_attributes.only(dirty_attributes(old_originals).keys).keys - self.class.read_only.stringify_values).length == (dirty_attributes(old_originals).keys - old_originals.diff(original_values).keys - self.class.read_only.stringify_values).length # 'Revert' fields I didn't modify to equal the values of the more up-to-date record just loaded. # Fields I didn't modify: dirty_attributes - dirty_attributes(old_originals).keys (dirty_attributes - dirty_attributes(old_originals).keys).each_key do |at| self.send(at + '=', original_values[at]) if respond_to?(at + '=') end ret = self.save end end # ret should be a false value if self has errors. Either way, ret gets the errors too. ret.errors << self.errors if self.error? # Should be true or false with an error attached. ret end |
#success? ⇒ Boolean
Returns success (true/false) status of the last quickbooks communication called from this object.
86 87 88 |
# File 'lib/quickbooks/base.rb', line 86 def success? @response_log.last.success? end |