quickbooks 0.4.0 → 0.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/History.txt +23 -0
- data/License.txt +54 -0
- data/Manifest.txt +73 -0
- data/README.txt +79 -0
- data/Rakefile +17 -78
- data/lib/quickbooks.rb +153 -7
- data/lib/quickbooks/adaptability.rb +67 -0
- data/lib/quickbooks/adapters/http_adapter.rb +94 -0
- data/lib/quickbooks/adapters/https_adapter.rb +57 -0
- data/lib/quickbooks/adapters/ole_adapter.rb +141 -110
- data/lib/quickbooks/adapters/spew_adapter.rb +39 -0
- data/lib/quickbooks/adapters/tcp_adapter.rb +71 -0
- data/lib/quickbooks/adapters/test_adapter.rb +62 -0
- data/lib/quickbooks/element.rb +385 -0
- data/lib/quickbooks/element_collection.rb +105 -0
- data/lib/quickbooks/extlib.rb +8 -0
- data/lib/quickbooks/extlib/assertions.rb +8 -0
- data/lib/quickbooks/extlib/class.rb +98 -0
- data/lib/quickbooks/extlib/days_and_times.rb +10 -0
- data/lib/quickbooks/extlib/days_and_times/duration.rb +362 -0
- data/lib/quickbooks/extlib/days_and_times/numeric.rb +48 -0
- data/lib/quickbooks/extlib/days_and_times/object.rb +19 -0
- data/lib/quickbooks/extlib/days_and_times/time.rb +137 -0
- data/lib/quickbooks/extlib/hash.rb +327 -0
- data/lib/quickbooks/extlib/hook.rb +366 -0
- data/lib/quickbooks/extlib/inflection.rb +436 -0
- data/lib/quickbooks/extlib/logger.rb +202 -0
- data/lib/quickbooks/extlib/object.rb +162 -0
- data/lib/quickbooks/extlib/pathname.rb +15 -0
- data/lib/quickbooks/extlib/rubygems.rb +38 -0
- data/lib/quickbooks/extlib/string.rb +32 -0
- data/lib/quickbooks/extlib/time.rb +41 -0
- data/lib/quickbooks/model.rb +503 -121
- data/lib/quickbooks/option.rb +95 -0
- data/lib/quickbooks/property.rb +69 -0
- data/lib/quickbooks/ruby_ext.rb +251 -0
- data/lib/quickbooks/type.rb +75 -0
- data/lib/quickbooks/types.rb +58 -0
- data/lib/quickbooks/version.rb +10 -0
- data/lib/quickbooks/xsd.rb +243 -0
- data/lib/quickbooks/xsd/attribute.rb +57 -0
- data/lib/quickbooks/xsd/choice.rb +94 -0
- data/lib/quickbooks/xsd/complex_type.rb +77 -0
- data/lib/quickbooks/xsd/element.rb +214 -0
- data/lib/quickbooks/xsd/group.rb +94 -0
- data/lib/quickbooks/xsd/restriction.rb +51 -0
- data/lib/quickbooks/xsd/sequence.rb +85 -0
- data/lib/quickbooks/xsd/simple_type.rb +87 -0
- data/lib/quickbooks/xsd/union.rb +70 -0
- data/lib/quickbooks/xsd/validation.rb +89 -0
- data/lib/quickbooks/xsd/xml_parse.rb +80 -0
- data/quickbooks.gemspec +36 -0
- data/source/qbxml21_demo.xsd +2223 -0
- data/source/qbxmlops_demo.xsd +483 -0
- data/source/qbxmltypes.xsd +160 -0
- data/spec/association_spec.rb +5 -0
- data/spec/element_collection_spec.rb +8 -0
- data/spec/find_spec.rb +30 -0
- data/spec/lib/quickbooks/element_spec.rb +83 -0
- data/spec/lib/quickbooks/elements/sales_order_add_spec.rb +14 -0
- data/spec/lib/quickbooks/elements/vendor_add_spec.rb +78 -0
- data/spec/lib/quickbooks/model_spec.rb +89 -0
- data/spec/lib/quickbooks/models/customer_spec.rb +52 -0
- data/spec/lib/quickbooks/models/invoice_spec.rb +12 -0
- data/spec/lib/quickbooks/models/sales_order_line_spec.rb +0 -0
- data/spec/lib/quickbooks/models/sales_order_spec.rb +145 -0
- data/spec/lib/quickbooks/xsd/choice_spec.rb +18 -0
- data/spec/pending_spec.rb +11 -0
- data/spec/quickbooks_spec.rb +38 -0
- data/spec/repeatable_spec.rb +20 -0
- data/spec/requires_spec.rb +10 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/validation_spec.rb +24 -0
- metadata +133 -285
- metadata.gz.sig +0 -0
- data/LICENSE +0 -16
- data/README +0 -49
- data/doc/classes/Array.html +0 -368
- data/doc/classes/Array.src/M000026.html +0 -18
- data/doc/classes/Array.src/M000027.html +0 -21
- data/doc/classes/Array.src/M000028.html +0 -18
- data/doc/classes/Array.src/M000029.html +0 -19
- data/doc/classes/Array.src/M000030.html +0 -18
- data/doc/classes/Array.src/M000031.html +0 -23
- data/doc/classes/Array.src/M000032.html +0 -18
- data/doc/classes/Array.src/M000033.html +0 -18
- data/doc/classes/Array.src/M000034.html +0 -18
- data/doc/classes/Array.src/M000035.html +0 -19
- data/doc/classes/Array.src/M000036.html +0 -18
- data/doc/classes/Array.src/M000037.html +0 -23
- data/doc/classes/Array.src/M000038.html +0 -18
- data/doc/classes/Array.src/M000039.html +0 -21
- data/doc/classes/Array.src/M000040.html +0 -18
- data/doc/classes/Array.src/M000041.html +0 -18
- data/doc/classes/Class.html +0 -171
- data/doc/classes/Class.src/M000042.html +0 -18
- data/doc/classes/Class.src/M000043.html +0 -18
- data/doc/classes/Hash.html +0 -516
- data/doc/classes/Hash.src/M000001.html +0 -18
- data/doc/classes/Hash.src/M000002.html +0 -21
- data/doc/classes/Hash.src/M000003.html +0 -18
- data/doc/classes/Hash.src/M000004.html +0 -21
- data/doc/classes/Hash.src/M000005.html +0 -18
- data/doc/classes/Hash.src/M000006.html +0 -20
- data/doc/classes/Hash.src/M000007.html +0 -18
- data/doc/classes/Hash.src/M000008.html +0 -22
- data/doc/classes/Hash.src/M000009.html +0 -18
- data/doc/classes/Hash.src/M000010.html +0 -21
- data/doc/classes/Hash.src/M000011.html +0 -24
- data/doc/classes/Hash.src/M000012.html +0 -18
- data/doc/classes/Hash.src/M000013.html +0 -21
- data/doc/classes/Hash.src/M000014.html +0 -18
- data/doc/classes/Hash.src/M000015.html +0 -21
- data/doc/classes/Hash.src/M000016.html +0 -18
- data/doc/classes/Hash.src/M000017.html +0 -21
- data/doc/classes/Hash.src/M000018.html +0 -27
- data/doc/classes/Hash.src/M000019.html +0 -20
- data/doc/classes/Hash.src/M000020.html +0 -18
- data/doc/classes/Hash.src/M000021.html +0 -18
- data/doc/classes/Hash.src/M000022.html +0 -18
- data/doc/classes/Hash.src/M000023.html +0 -18
- data/doc/classes/Hash.src/M000024.html +0 -18
- data/doc/classes/Hash.src/M000025.html +0 -28
- data/doc/classes/Object.html +0 -278
- data/doc/classes/Object.src/M000044.html +0 -24
- data/doc/classes/Object.src/M000045.html +0 -19
- data/doc/classes/Object.src/M000046.html +0 -24
- data/doc/classes/Object.src/M000047.html +0 -18
- data/doc/classes/Object.src/M000048.html +0 -19
- data/doc/classes/Object.src/M000049.html +0 -18
- data/doc/classes/Object.src/M000050.html +0 -18
- data/doc/classes/Object.src/M000051.html +0 -18
- data/doc/classes/Qbxml.html +0 -131
- data/doc/classes/Qbxml/Request.html +0 -224
- data/doc/classes/Qbxml/Request.src/M000132.html +0 -66
- data/doc/classes/Qbxml/Request.src/M000133.html +0 -19
- data/doc/classes/Qbxml/Request.src/M000134.html +0 -83
- data/doc/classes/Qbxml/RequestSet.html +0 -199
- data/doc/classes/Qbxml/RequestSet.src/M000135.html +0 -22
- data/doc/classes/Qbxml/RequestSet.src/M000136.html +0 -26
- data/doc/classes/Qbxml/RequestSet.src/M000137.html +0 -18
- data/doc/classes/Qbxml/RequestSet.src/M000138.html +0 -22
- data/doc/classes/Qbxml/Response.html +0 -302
- data/doc/classes/Qbxml/Response.src/M000123.html +0 -24
- data/doc/classes/Qbxml/Response.src/M000124.html +0 -19
- data/doc/classes/Qbxml/Response.src/M000125.html +0 -55
- data/doc/classes/Qbxml/Response.src/M000126.html +0 -18
- data/doc/classes/Qbxml/Response.src/M000127.html +0 -18
- data/doc/classes/Qbxml/Response.src/M000128.html +0 -18
- data/doc/classes/Qbxml/Response.src/M000129.html +0 -18
- data/doc/classes/Qbxml/Response.src/M000130.html +0 -18
- data/doc/classes/Qbxml/Response.src/M000131.html +0 -63
- data/doc/classes/Qbxml/ResponseSet.html +0 -244
- data/doc/classes/Qbxml/ResponseSet.src/M000116.html +0 -22
- data/doc/classes/Qbxml/ResponseSet.src/M000117.html +0 -26
- data/doc/classes/Qbxml/ResponseSet.src/M000118.html +0 -24
- data/doc/classes/Qbxml/ResponseSet.src/M000119.html +0 -20
- data/doc/classes/Qbxml/ResponseSet.src/M000120.html +0 -27
- data/doc/classes/Qbxml/ResponseSet.src/M000121.html +0 -18
- data/doc/classes/Qbxml/ResponseSet.src/M000122.html +0 -18
- data/doc/classes/Quickbooks.html +0 -196
- data/doc/classes/Quickbooks/Address.html +0 -139
- data/doc/classes/Quickbooks/Address.src/M000115.html +0 -19
- data/doc/classes/Quickbooks/Base.html +0 -567
- data/doc/classes/Quickbooks/Base.src/M000095.html +0 -18
- data/doc/classes/Quickbooks/Base.src/M000096.html +0 -20
- data/doc/classes/Quickbooks/Base.src/M000097.html +0 -19
- data/doc/classes/Quickbooks/Base.src/M000098.html +0 -18
- data/doc/classes/Quickbooks/Base.src/M000099.html +0 -19
- data/doc/classes/Quickbooks/Base.src/M000100.html +0 -30
- data/doc/classes/Quickbooks/Base.src/M000101.html +0 -22
- data/doc/classes/Quickbooks/Base.src/M000102.html +0 -30
- data/doc/classes/Quickbooks/Base.src/M000103.html +0 -19
- data/doc/classes/Quickbooks/Base.src/M000104.html +0 -19
- data/doc/classes/Quickbooks/Base.src/M000105.html +0 -18
- data/doc/classes/Quickbooks/Base.src/M000106.html +0 -18
- data/doc/classes/Quickbooks/Base.src/M000107.html +0 -19
- data/doc/classes/Quickbooks/Base.src/M000108.html +0 -18
- data/doc/classes/Quickbooks/Base.src/M000109.html +0 -45
- data/doc/classes/Quickbooks/Base.src/M000110.html +0 -18
- data/doc/classes/Quickbooks/Base.src/M000111.html +0 -18
- data/doc/classes/Quickbooks/Base.src/M000112.html +0 -20
- data/doc/classes/Quickbooks/BillAddress.html +0 -113
- data/doc/classes/Quickbooks/CreditCardInfo.html +0 -113
- data/doc/classes/Quickbooks/Customer.html +0 -113
- data/doc/classes/Quickbooks/CustomerTypeRef.html +0 -113
- data/doc/classes/Quickbooks/Deleted.html +0 -113
- data/doc/classes/Quickbooks/ItemSalesTaxRef.html +0 -113
- data/doc/classes/Quickbooks/JobTypeRef.html +0 -113
- data/doc/classes/Quickbooks/ListDeleted.html +0 -139
- data/doc/classes/Quickbooks/ListDeleted.src/M000114.html +0 -18
- data/doc/classes/Quickbooks/ListItem.html +0 -170
- data/doc/classes/Quickbooks/ListItem.src/M000093.html +0 -20
- data/doc/classes/Quickbooks/ListItem.src/M000094.html +0 -18
- data/doc/classes/Quickbooks/Model.html +0 -462
- data/doc/classes/Quickbooks/Model.src/M000073.html +0 -24
- data/doc/classes/Quickbooks/Model.src/M000074.html +0 -19
- data/doc/classes/Quickbooks/Model.src/M000075.html +0 -18
- data/doc/classes/Quickbooks/Model.src/M000076.html +0 -18
- data/doc/classes/Quickbooks/Model.src/M000077.html +0 -18
- data/doc/classes/Quickbooks/Model.src/M000078.html +0 -22
- data/doc/classes/Quickbooks/Model.src/M000079.html +0 -32
- data/doc/classes/Quickbooks/Model.src/M000080.html +0 -32
- data/doc/classes/Quickbooks/Model.src/M000081.html +0 -18
- data/doc/classes/Quickbooks/Model.src/M000082.html +0 -18
- data/doc/classes/Quickbooks/Model.src/M000083.html +0 -22
- data/doc/classes/Quickbooks/Model.src/M000084.html +0 -23
- data/doc/classes/Quickbooks/Model.src/M000085.html +0 -18
- data/doc/classes/Quickbooks/Model.src/M000086.html +0 -21
- data/doc/classes/Quickbooks/Model.src/M000087.html +0 -26
- data/doc/classes/Quickbooks/Model.src/M000088.html +0 -26
- data/doc/classes/Quickbooks/Model.src/M000089.html +0 -26
- data/doc/classes/Quickbooks/Model.src/M000090.html +0 -21
- data/doc/classes/Quickbooks/Model.src/M000091.html +0 -23
- data/doc/classes/Quickbooks/OleAdapter.html +0 -129
- data/doc/classes/Quickbooks/OleAdapter/Connection.html +0 -343
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000058.html +0 -18
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000059.html +0 -19
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000060.html +0 -24
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000061.html +0 -18
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000062.html +0 -18
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000063.html +0 -21
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000064.html +0 -24
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000065.html +0 -20
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000066.html +0 -24
- data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000067.html +0 -24
- data/doc/classes/Quickbooks/OleAdapter/Ole.html +0 -209
- data/doc/classes/Quickbooks/OleAdapter/Ole.src/M000068.html +0 -21
- data/doc/classes/Quickbooks/OleAdapter/Ole.src/M000069.html +0 -22
- data/doc/classes/Quickbooks/OleAdapter/Ole.src/M000070.html +0 -18
- data/doc/classes/Quickbooks/ParentRef.html +0 -113
- data/doc/classes/Quickbooks/PreferredPaymentMethodRef.html +0 -113
- data/doc/classes/Quickbooks/PriceLevelRef.html +0 -113
- data/doc/classes/Quickbooks/QbxmlDebugAdapter.html +0 -111
- data/doc/classes/Quickbooks/QbxmlDebugAdapter/Connection.html +0 -139
- data/doc/classes/Quickbooks/QbxmlDebugAdapter/Connection.src/M000057.html +0 -18
- data/doc/classes/Quickbooks/Ref.html +0 -146
- data/doc/classes/Quickbooks/Ref.src/M000113.html +0 -18
- data/doc/classes/Quickbooks/SalesRepRef.html +0 -113
- data/doc/classes/Quickbooks/SalesTaxCodeRef.html +0 -113
- data/doc/classes/Quickbooks/ShipAddress.html +0 -113
- data/doc/classes/Quickbooks/TermsRef.html +0 -113
- data/doc/classes/Quickbooks/Transaction.html +0 -154
- data/doc/classes/Quickbooks/Transaction.src/M000071.html +0 -19
- data/doc/classes/Quickbooks/Transaction.src/M000072.html +0 -18
- data/doc/classes/Quickbooks/TxnDeleted.html +0 -139
- data/doc/classes/Quickbooks/TxnDeleted.src/M000092.html +0 -18
- data/doc/classes/String.html +0 -203
- data/doc/classes/String.src/M000052.html +0 -18
- data/doc/classes/String.src/M000053.html +0 -18
- data/doc/classes/String.src/M000054.html +0 -18
- data/doc/classes/String.src/M000055.html +0 -18
- data/doc/classes/String.src/M000056.html +0 -18
- data/doc/created.rid +0 -1
- data/doc/files/LICENSE.html +0 -129
- data/doc/files/README.html +0 -225
- data/doc/files/lib/qbxml/request_rb.html +0 -110
- data/doc/files/lib/qbxml/response_rb.html +0 -109
- data/doc/files/lib/qbxml/support_rb.html +0 -101
- data/doc/files/lib/qbxml_rb.html +0 -122
- data/doc/files/lib/quickbooks/adapters/ole_adapter_rb.html +0 -108
- data/doc/files/lib/quickbooks/adapters/qbxml_debug_adapter_rb.html +0 -108
- data/doc/files/lib/quickbooks/base_rb.html +0 -327
- data/doc/files/lib/quickbooks/model_rb.html +0 -108
- data/doc/files/lib/quickbooks/models/common/address_rb.html +0 -101
- data/doc/files/lib/quickbooks/models/common/all_refs_rb.html +0 -101
- data/doc/files/lib/quickbooks/models/customer/credit_card_info_rb.html +0 -101
- data/doc/files/lib/quickbooks/models/customer_rb.html +0 -110
- data/doc/files/lib/quickbooks/models/deleted_rb.html +0 -101
- data/doc/files/lib/quickbooks/models/list_item_rb.html +0 -101
- data/doc/files/lib/quickbooks/models/transaction_rb.html +0 -101
- data/doc/files/lib/quickbooks/ruby_magic_rb.html +0 -120
- data/doc/files/lib/quickbooks_rb.html +0 -125
- data/doc/fr_class_index.html +0 -64
- data/doc/fr_file_index.html +0 -45
- data/doc/fr_method_index.html +0 -164
- data/doc/index.html +0 -24
- data/doc/rdoc-style.css +0 -208
- data/lib/qbxml.rb +0 -3
- data/lib/qbxml/request.rb +0 -207
- data/lib/qbxml/response.rb +0 -197
- data/lib/qbxml/support.rb +0 -130
- data/lib/quickbooks/adapters/qbxml_debug_adapter.rb +0 -10
- data/lib/quickbooks/base.rb +0 -277
- data/lib/quickbooks/models/common/address.rb +0 -14
- data/lib/quickbooks/models/common/all_refs.rb +0 -37
- data/lib/quickbooks/models/customer.rb +0 -70
- data/lib/quickbooks/models/customer/credit_card_info.rb +0 -5
- data/lib/quickbooks/models/deleted.rb +0 -22
- data/lib/quickbooks/models/list_item.rb +0 -41
- data/lib/quickbooks/models/transaction.rb +0 -49
- data/lib/quickbooks/ruby_magic.rb +0 -213
data/lib/qbxml.rb
DELETED
data/lib/qbxml/request.rb
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
require 'qbxml/support'
|
|
2
|
-
require 'builder'
|
|
3
|
-
require 'hash_magic'
|
|
4
|
-
|
|
5
|
-
module Qbxml
|
|
6
|
-
VERSION = '6.0'
|
|
7
|
-
|
|
8
|
-
# module RequestSetArrayExt
|
|
9
|
-
# end
|
|
10
|
-
|
|
11
|
-
class RequestSet
|
|
12
|
-
include Enumerable
|
|
13
|
-
def set
|
|
14
|
-
unless @set.is_a?(Array)
|
|
15
|
-
@set = []
|
|
16
|
-
# @set.extend(Qbxml::RequestSetArrayExt)
|
|
17
|
-
end
|
|
18
|
-
@set
|
|
19
|
-
end
|
|
20
|
-
delegate_methods [:each, :length, :first, :last, :[], :map, :join] => :set
|
|
21
|
-
def <<(qbxml_request)
|
|
22
|
-
if qbxml_request.is_a?(Qbxml::Request)
|
|
23
|
-
set << qbxml_request
|
|
24
|
-
elsif qbxml_request.respond_to?(:each)
|
|
25
|
-
qbxml_request.each do |request|
|
|
26
|
-
self << request
|
|
27
|
-
end
|
|
28
|
-
else
|
|
29
|
-
raise ArgumentError, "Cannot add object of type #{qbxml_request.class.name} to a Qbxml::RequestSet"
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def initialize(*requests)
|
|
34
|
-
self << requests
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def to_xml
|
|
38
|
-
pre = <<-thequickbooks_qbxmlrequestsetxml
|
|
39
|
-
<?xml version="1.0" ?>
|
|
40
|
-
<?qbxml version="#{Qbxml::VERSION}" ?>
|
|
41
|
-
<QBXML>
|
|
42
|
-
<QBXMLMsgsRq onError="stopOnError">
|
|
43
|
-
thequickbooks_qbxmlrequestsetxml
|
|
44
|
-
requests = map {|x| x.to_xml(false)}.join
|
|
45
|
-
post = <<-thequickbooks_qbxmlrequestsetxml
|
|
46
|
-
</QBXMLMsgsRq>
|
|
47
|
-
</QBXML>
|
|
48
|
-
thequickbooks_qbxmlrequestsetxml
|
|
49
|
-
# puts pre + requests + post
|
|
50
|
-
pre + requests + post
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
class Request
|
|
55
|
-
# 1. List queries (:query)
|
|
56
|
-
# Request.new(object, :query) # <= will return the record matching the object supplied (automatically searches by list_id or txn_id)
|
|
57
|
-
# Request.new(Customer, :query, :limit => 1) # <= will return the first customer
|
|
58
|
-
# Request.new(Customer, :query, /some match/) # <= will return all customers matching the regexp
|
|
59
|
-
# 2. Deleted queries (:deleted)
|
|
60
|
-
# Request.new(object, :deleted) # <= INVALID!! (besides, you wouldn't have an object to check up on anyway :P )
|
|
61
|
-
# Request.new(Customer, :deleted) # <= will return all deleted Customers
|
|
62
|
-
# Request.new(Customer, :deleted, :deleted_date_range_filter => {'from_deleted_date' => Date.parse('2008/10/05')}) # <= will return all Customers deleted since 5 October 2008
|
|
63
|
-
# 3. Object-specific transaction query (:transaction)
|
|
64
|
-
# Request.new(Transaction, :query) # <= will return the transaction matching the object supplied
|
|
65
|
-
# 4. Mod requests (:mod)
|
|
66
|
-
# Request.new(object, :mod) # <= will update the object
|
|
67
|
-
# 5. Delete requests (:delete)
|
|
68
|
-
# Request.new(object, :delete) # <= will delete the object
|
|
69
|
-
# We want the attributes of the object when we are updating, but no other time.
|
|
70
|
-
def initialize(object, type, options_or_regexp={})
|
|
71
|
-
options = options_or_regexp.is_a?(Regexp) ? {:matches => options_or_regexp} : options_or_regexp
|
|
72
|
-
@type = type
|
|
73
|
-
raise ArgumentError, "Qbxml::Requests can only be of one of the following types: :query, :transaction, :any_transaction, :mod, :add, :delete, :deleted, or :report" unless @type.is_one_of?(:query, :transaction, :any_transaction, :mod, :report, :add, :delete, :deleted)
|
|
74
|
-
@klass = object.is_a?(Class) ? object : object.class
|
|
75
|
-
@object = object
|
|
76
|
-
@options = options
|
|
77
|
-
|
|
78
|
-
# Transform the options received for :deleted requests.
|
|
79
|
-
# This way, Request.new(Customer, :deleted) == Request.new(ListDeleted, :list_del_type => 'Customer')
|
|
80
|
-
# and Request.new(Transaction, :deleted) == Request.new(TxnDeleted, :txn_del_type => 'Transaction')
|
|
81
|
-
if @type == :deleted
|
|
82
|
-
case @klass.ListOrTxn
|
|
83
|
-
when 'List'
|
|
84
|
-
@options[:list_del_type] = @klass.lone_name
|
|
85
|
-
@klass = Quickbooks::ListDeleted
|
|
86
|
-
when 'Txn'
|
|
87
|
-
@options[:txn_del_type] = @klass.lone_name
|
|
88
|
-
@klass = Quickbooks::TxnDeleted
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Return only specific properties: Request.new(Customer, :query, :only => [:list_id, :full_name]); Quickbooks::Customer.first(:only => :list_id)
|
|
93
|
-
@ret_elements = @options.delete(:only).to_a.only(@klass.properties).ordered(@klass.properties).stringify_values.camelize_values!(Quickbooks::CAMELIZE_EXCEPTIONS) if @options.has_key?(:only)
|
|
94
|
-
|
|
95
|
-
# Includes only valid filters + aliases for valid filters, # => {underscore/slashed keys + aliases}
|
|
96
|
-
# then transforms aliased filters to real filters, # => {underscore/slashed keys}
|
|
97
|
-
# then camelizes keys to prepare for writing to XML, # => {}
|
|
98
|
-
# lastly orders the keys to a valid filter order.
|
|
99
|
-
|
|
100
|
-
# Study the following:
|
|
101
|
-
# @klass.filter_aliases = {'deleted_after' => 'deleted_date_range_filter/from_deleted_date'}
|
|
102
|
-
# @klass.valid_filters = ['deleted_date_range_filter/from_deleted_date']
|
|
103
|
-
# {:deleted_after => "2008-03-20T11:20:26-04:00"}.slashed.
|
|
104
|
-
# only(@klass.valid_filters + @klass.filter_aliases.slashed.flat.keys).
|
|
105
|
-
# transform_keys!(@klass.filter_aliases.slashed.flat).
|
|
106
|
-
# slash_camelize_keys!(Quickbooks::CAMELIZE_EXCEPTIONS).slashed.
|
|
107
|
-
# ordered!(@klass.camelized_valid_filters).slashed.expand
|
|
108
|
-
# # => {"DeletedDateRangeFilter" => {"FromDeletedDate" => "2008-03-20T11:20:26-04:00"}}
|
|
109
|
-
@filters = @options.delete(:filters) || @options.slashed.
|
|
110
|
-
only(@klass.valid_filters + @klass.filter_aliases.slashed.flat.keys).
|
|
111
|
-
transform_keys!(@klass.filter_aliases.slashed.flat).
|
|
112
|
-
slash_camelize_keys!(Quickbooks::CAMELIZE_EXCEPTIONS).
|
|
113
|
-
ordered!(@klass.camelized_valid_filters)
|
|
114
|
-
@filters = @filters.to_hash unless @filters.is_a?(Hash)
|
|
115
|
-
@filters = @filters['FILTERS'] if @filters.keys == ['FILTERS'] # So if you include an xml-formatted string of filters, you can simply wrap them in <FILTERS></FILTERS> as a root key
|
|
116
|
-
|
|
117
|
-
# Complain if:
|
|
118
|
-
# 1) type is :mod or :delete, and object supplied is not a valid model
|
|
119
|
-
raise ArgumentError, "A Quickbooks record object must be supplied to perform an add, mod or del action" if @type.is_one_of?(:add, :mod, :delete) && !@object.is_a?(Quickbooks::Base)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def self.next_request_id
|
|
123
|
-
@request_id ||= 0
|
|
124
|
-
@request_id += 1
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# This is where the magic happens to convert a request object into xml worthy of quickbooks.
|
|
128
|
-
def to_xml(as_set=true)
|
|
129
|
-
return (RequestSet.new(self)).to_xml if as_set # Simple call yields xml as a single request in a request set. However, if the xml for the lone request is required, pass false.
|
|
130
|
-
req = Builder::XmlMarkup.new(:indent => 2)
|
|
131
|
-
request_root, container = case
|
|
132
|
-
when @type.is_one_of?(:query)
|
|
133
|
-
["#{@klass.class_leaf_name}QueryRq", nil]
|
|
134
|
-
when @type == :add
|
|
135
|
-
["#{@klass.class_leaf_name}AddRq", "#{@klass.class_leaf_name}Add"]
|
|
136
|
-
when @type == :mod
|
|
137
|
-
["#{@klass.class_leaf_name}ModRq", "#{@klass.class_leaf_name}Mod"]
|
|
138
|
-
when @type == :delete
|
|
139
|
-
["#{@klass.ListOrTxn}DelRq", nil]
|
|
140
|
-
when @type == :deleted
|
|
141
|
-
["#{@klass.ListOrTxn}DeletedQueryRq", nil]
|
|
142
|
-
else
|
|
143
|
-
raise RuntimeError, "Could not convert this request to qbxml!\n#{self.inspect}"
|
|
144
|
-
end
|
|
145
|
-
inner_stuff = lambda {
|
|
146
|
-
deep_tag = lambda {|k,v|
|
|
147
|
-
if v.is_a?(Hash)
|
|
148
|
-
if k == ''
|
|
149
|
-
v.each { |k,v|
|
|
150
|
-
deep_tag.call(k,v)
|
|
151
|
-
}
|
|
152
|
-
else
|
|
153
|
-
req.tag!(k.camelize) { v.each { |k,v| deep_tag.call(k,v) } }
|
|
154
|
-
end
|
|
155
|
-
else
|
|
156
|
-
req.tag!(k.camelize,uncast(v))
|
|
157
|
-
end
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
# Add the specific elements for the respective request type
|
|
161
|
-
if @type.is_one_of?(:add, :mod)
|
|
162
|
-
if @type == :mod
|
|
163
|
-
# First the ObjectId:
|
|
164
|
-
req.tag!(@klass.ListOrTxn + 'ID', @object.send("#{@klass.ListOrTxn}Id".underscore))
|
|
165
|
-
# Second the EditSequence
|
|
166
|
-
req.tag!('EditSequence', @object.send(:edit_sequence))
|
|
167
|
-
end
|
|
168
|
-
# Then, all the dirty_attributes
|
|
169
|
-
deep_tag.call('',@object.to_dirty_hash) # (this is an hash statically ordered to the model's qbxml attribute order)
|
|
170
|
-
elsif @type == :query && @object.class == @klass
|
|
171
|
-
# Sent an instance object for a query - we should include the ListId/TxnId (then other filters?)
|
|
172
|
-
req.tag!(@klass.ListOrTxn + 'ID', @object.send("#{@klass.ListOrTxn}Id".underscore))
|
|
173
|
-
deep_tag.call('', @filters)
|
|
174
|
-
elsif @type == :delete
|
|
175
|
-
req.tag!(@klass.ListOrTxn + 'DelType', @klass.class_leaf_name)
|
|
176
|
-
req.tag!(@klass.ListOrTxn + 'ID', @object.send("#{@klass.ListOrTxn}Id".underscore))
|
|
177
|
-
else
|
|
178
|
-
# just filters
|
|
179
|
-
deep_tag.call('', @filters)
|
|
180
|
-
end
|
|
181
|
-
# Lastly, specify the fields to return, if desired
|
|
182
|
-
@ret_elements.each { |r| req.tag!('IncludeRetElement', r) } if @ret_elements.is_a?(Array) && @ret_elements.length > 0
|
|
183
|
-
}
|
|
184
|
-
req.tag!(request_root, :requestID => self.class.next_request_id) {
|
|
185
|
-
if container
|
|
186
|
-
req.tag!(container) {
|
|
187
|
-
inner_stuff.call
|
|
188
|
-
}
|
|
189
|
-
else
|
|
190
|
-
inner_stuff.call
|
|
191
|
-
end
|
|
192
|
-
}
|
|
193
|
-
# puts req.target!
|
|
194
|
-
req.target!
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
private
|
|
198
|
-
def uncast(v)
|
|
199
|
-
case
|
|
200
|
-
when v.respond_to?(:xmlschema)
|
|
201
|
-
v.xmlschema
|
|
202
|
-
else
|
|
203
|
-
v
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
end
|
data/lib/qbxml/response.rb
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
require 'qbxml/support'
|
|
2
|
-
require 'formatted_string'
|
|
3
|
-
|
|
4
|
-
module Qbxml
|
|
5
|
-
# module ResponseSetArrayExt
|
|
6
|
-
# end
|
|
7
|
-
|
|
8
|
-
class ResponseSet
|
|
9
|
-
include Enumerable
|
|
10
|
-
def set
|
|
11
|
-
unless @set.is_a?(Array)
|
|
12
|
-
@set = []
|
|
13
|
-
# @set.extend(Qbxml::ResponseSetArrayExt)
|
|
14
|
-
end
|
|
15
|
-
@set
|
|
16
|
-
end
|
|
17
|
-
delegate_methods [:each, :length, :first, :last, :[], :map, :join] => :set
|
|
18
|
-
def <<(qbxml_response)
|
|
19
|
-
if qbxml_response.is_a?(Qbxml::Response)
|
|
20
|
-
set << qbxml_response
|
|
21
|
-
elsif qbxml_response.respond_to?(:each)
|
|
22
|
-
qbxml_response.each do |response|
|
|
23
|
-
self << response
|
|
24
|
-
end
|
|
25
|
-
else
|
|
26
|
-
raise ArgumentError, "Cannot add object of type #{qbxml_response.class.name} to a Qbxml::ResponseSet"
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def initialize(xml_or_hash)
|
|
31
|
-
if(xml_or_hash.is_a?(Hash))
|
|
32
|
-
self.append_from_hash(xml_or_hash)
|
|
33
|
-
elsif(xml_or_hash.is_a?(String))
|
|
34
|
-
self.append_from_xml(xml_or_hash)
|
|
35
|
-
else
|
|
36
|
-
raise ArgumentError, "Qbxml::ResponseSet must be initialized with either a Hash or an xml-formatted String."
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def append_from_xml(xml)
|
|
41
|
-
# puts "ResponseXML:"
|
|
42
|
-
# puts xml
|
|
43
|
-
self.append_from_hash(xml.formatted(:xml).to_hash)
|
|
44
|
-
end
|
|
45
|
-
def append_from_hash(hsh)
|
|
46
|
-
to_append = []
|
|
47
|
-
hsh = hsh['QBXML'] if hsh.has_key?('QBXML')
|
|
48
|
-
hsh = hsh['QBXMLMsgsRs'] if hsh.has_key?('QBXMLMsgsRs')
|
|
49
|
-
# responses will contain one or more keys.
|
|
50
|
-
hsh.each_key do |name|
|
|
51
|
-
# response_type is either a single response object, or an array of response objects. Force it into an array:
|
|
52
|
-
responses = hsh[name].is_a?(Array) ? hsh[name] : [hsh[name]]
|
|
53
|
-
responses.each { |response| to_append << Response.new(name => response) }
|
|
54
|
-
end
|
|
55
|
-
self << to_append
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
class << self
|
|
59
|
-
def from_xml(xml)
|
|
60
|
-
new.append_from_xml(xml)
|
|
61
|
-
end
|
|
62
|
-
def from_hash(hsh)
|
|
63
|
-
new.append_from_hash(hsh)
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
class Response
|
|
69
|
-
attr_accessor :response_type, :status, :message, :severity, :ret_items
|
|
70
|
-
# For Development purposes:
|
|
71
|
-
attr_accessor :raw_response
|
|
72
|
-
|
|
73
|
-
def initialize(xml_or_hash)
|
|
74
|
-
if(xml_or_hash.is_a?(Hash))
|
|
75
|
-
self.import_from_hash(xml_or_hash)
|
|
76
|
-
elsif(xml_or_hash.is_a?(String))
|
|
77
|
-
self.import_from_xml(xml_or_hash)
|
|
78
|
-
else
|
|
79
|
-
raise ArgumentError, "Qbxml::ResponseSet must be initialized with either a Hash or an xml-formatted String."
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def import_from_xml(xml)
|
|
84
|
-
self.import_from_hash(xml.formatted(:xml).to_hash)
|
|
85
|
-
self
|
|
86
|
-
end
|
|
87
|
-
def import_from_hash(hsh)
|
|
88
|
-
raise ArgumentError, "Hash passed to Qbxml::Response.from_hash must contain only one top-level key" unless hsh.keys.length == 1
|
|
89
|
-
name = hsh.keys.first
|
|
90
|
-
# for development
|
|
91
|
-
self.raw_response = hsh
|
|
92
|
-
# * * * *
|
|
93
|
-
hsh = hsh[name]
|
|
94
|
-
|
|
95
|
-
self.status = hsh['statusCode'].to_i
|
|
96
|
-
self.severity = hsh['statusSeverity']
|
|
97
|
-
self.message = hsh['statusMessage']
|
|
98
|
-
# if self.status == 0 # Status is good, proceed with eating the request.
|
|
99
|
-
# <ListDeletedQueryRs requestID="5" statusCode="0" statusSeverity="Info" statusMessage="Status OK">
|
|
100
|
-
# <ListDeletedRet>
|
|
101
|
-
# <ListDelType>Customer</ListDelType>
|
|
102
|
-
# <ListID>80000030-1203622308</ListID>
|
|
103
|
-
# <TimeCreated>2008-02-21T14:31:48-05:00</TimeCreated>
|
|
104
|
-
# <TimeDeleted>2008-03-18T17:31:12-05:00</TimeDeleted>
|
|
105
|
-
# <FullName>Rachel Parker</FullName>
|
|
106
|
-
# </ListDeletedRet>
|
|
107
|
-
# </ListDeletedQueryRs>
|
|
108
|
-
if m = name.match(/^(List|Txn)Del(etedQuery)?Rs$/)
|
|
109
|
-
# (List|Txn)DelRs, or (List|Txn)DeletedQueryRs - both return just a few attributes, like ListID / TxnID and TimeDeleted
|
|
110
|
-
list_or_txn = m[1]
|
|
111
|
-
long_name = m[1]+'Del'+m[2].to_s
|
|
112
|
-
ret_key = long_name.gsub(/Query$/,'')+'Ret'
|
|
113
|
-
self.ret_items = hsh[ret_key].is_a?(Array) ? hsh[ret_key] : [hsh[ret_key]].compact # Force to be an array - it's return items!
|
|
114
|
-
self.response_type = self.ret_items.empty? ? m[1] : self.ret_items[0][list_or_txn+'DelType']
|
|
115
|
-
elsif m = name.match(/^((?:[A-Za-z][a-z]+)+)(Query|Mod|Add)Rs$/)
|
|
116
|
-
self.response_type = m[1]
|
|
117
|
-
self.ret_items = hsh[self.response_type+'Ret']
|
|
118
|
-
else
|
|
119
|
-
raise "Could not read this response:\n#{self.raw_response.inspect}"
|
|
120
|
-
end
|
|
121
|
-
# else # Status is bad.
|
|
122
|
-
|
|
123
|
-
# end
|
|
124
|
-
# puts self.inspect
|
|
125
|
-
self
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
class << self
|
|
130
|
-
def from_xml(xml)
|
|
131
|
-
new.import_from_xml(xml)
|
|
132
|
-
end
|
|
133
|
-
def from_hash(hsh)
|
|
134
|
-
new.import_from_hash(hsh)
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def instantiatable? # Just checks to see if it can create an object of this type, and if there is actually data to instantiate
|
|
139
|
-
self.response_type ? (Quickbooks.const_defined?(self.response_type) && self.ret_items.is_a?(Hash) || (self.ret_items.is_a?(Array) && self.ret_items[0].is_a?(Hash))) : false
|
|
140
|
-
end
|
|
141
|
-
def success?
|
|
142
|
-
self.status == 0
|
|
143
|
-
end
|
|
144
|
-
def error?
|
|
145
|
-
!success?
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def instantiate(reinstantiate=nil)
|
|
149
|
-
objs = []
|
|
150
|
-
(self.ret_items.is_a?(Array) ? self.ret_items : [self.ret_items]).each do |ret_item|
|
|
151
|
-
obj = reinstantiate if reinstantiate
|
|
152
|
-
if instantiatable?
|
|
153
|
-
if self.status == 0
|
|
154
|
-
if obj.nil?
|
|
155
|
-
obj = "Quickbooks::#{self.response_type}".constantize.instantiate(ret_item)
|
|
156
|
-
else
|
|
157
|
-
obj.class.instantiate(obj, ret_item)
|
|
158
|
-
end
|
|
159
|
-
else
|
|
160
|
-
# Instantiatable, but some error status. For any error status
|
|
161
|
-
if obj.nil? # Must be a new object. Just as well, create a new object WITHOUT any original_attributes.
|
|
162
|
-
obj = "Quickbooks::#{self.response_type}".constantize.new(ret_item)
|
|
163
|
-
else # An existing object. Must be an update or delete request. Update object's original_attributes.
|
|
164
|
-
updated = []
|
|
165
|
-
ret_item.each do |k,v|
|
|
166
|
-
k = k.underscore
|
|
167
|
-
if obj.original_values[k] != v
|
|
168
|
-
updated << k
|
|
169
|
-
if obj.class.instance_variable_get('@object_properties').has_key?(k.to_sym)
|
|
170
|
-
obj.original_values[k] = obj.class.instance_variable_get('@object_properties')[k.to_sym].new(v)
|
|
171
|
-
else
|
|
172
|
-
obj.original_values[k] = v
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
# Update object's 'read-only' attributes (as well as in the original_values):
|
|
177
|
-
obj.class.read_only.stringify_values.camelize_values.each do |k|
|
|
178
|
-
obj.send(k.underscore + '=', ret_item[k]) if ret_item.has_key?(k) && obj.respond_to?(k.underscore + '=')
|
|
179
|
-
end
|
|
180
|
-
self.message = self.message + " Other properties were out of date: [" + updated.join(', ') + '].'
|
|
181
|
-
end
|
|
182
|
-
obj.errors << {:code => self.status, :message => self.message, :response => self}
|
|
183
|
-
end
|
|
184
|
-
else
|
|
185
|
-
if self.status == 0
|
|
186
|
-
obj.errors << {:code => nil, :message => "Cannot instantiate object of type #{self.response_type}!", :response => self}
|
|
187
|
-
else
|
|
188
|
-
obj.errors << {:code => self.status, :message => self.message, :response => self}
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
obj.response_log << self unless obj.nil?
|
|
192
|
-
objs << obj
|
|
193
|
-
end
|
|
194
|
-
objs.length > 1 ? objs : objs[0] # Single (fallback nil) if not more than one.
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
end
|
data/lib/qbxml/support.rb
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
gem 'formattedstring'
|
|
2
|
-
gem 'builder'
|
|
3
|
-
gem 'hash_magic'
|
|
4
|
-
|
|
5
|
-
class Object
|
|
6
|
-
# This allows one to effectively 'proxy' specific methods to be called on the return value of one of its methods.
|
|
7
|
-
# For example, obj.length could be delegated to do the same thing as obj.full_text.length
|
|
8
|
-
def delegate_methods(hsh)
|
|
9
|
-
raise ArgumentError, "delegate_methods should be called like: delegate_methods [:method1, :method2] => :delegated_to_method" unless hsh.keys.first.is_a?(Array)
|
|
10
|
-
methods = hsh.keys.first
|
|
11
|
-
delegate_to = hsh[methods]
|
|
12
|
-
methods.each do |method|
|
|
13
|
-
self.send(:eval, <<-ddddddd
|
|
14
|
-
def #{method}(*args, &block)
|
|
15
|
-
block_given? ? self.#{delegate_to}.#{method}(*args, &block) : self.#{delegate_to}.#{method}(*args)
|
|
16
|
-
end
|
|
17
|
-
ddddddd
|
|
18
|
-
)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Normally one would say, "if [:a, :b, :c].include?(:a)" -- which is backward thinking, instead you should use this magic:
|
|
23
|
-
# ":a.is_one_of?(:a, :b, :c)", or :a.is_one_of?([:a, :b, :c]).
|
|
24
|
-
def is_one_of?(*ary)
|
|
25
|
-
raise ArgumentError, "exists_in? requires an array to be passed" unless ary.is_a?(Array)
|
|
26
|
-
ary.flatten.include?(self)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
class Class
|
|
31
|
-
def lone_name
|
|
32
|
-
name.gsub(/.*::/, '')
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
class String
|
|
37
|
-
def constantize
|
|
38
|
-
Object.module_eval("::#{self}", __FILE__, __LINE__)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def underscore
|
|
42
|
-
gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def camelize
|
|
46
|
-
gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
class Array
|
|
51
|
-
def camelize_values(specials={})
|
|
52
|
-
self.dup.camelize_values!(specials)
|
|
53
|
-
end
|
|
54
|
-
def camelize_values!(specials={})
|
|
55
|
-
self.each_with_index do |v,i|
|
|
56
|
-
self[i] = specials.has_key?(v) ? specials[v] : (v.is_a?(Symbol) ? v.to_s.camelize.to_sym : v.camelize)
|
|
57
|
-
end
|
|
58
|
-
self
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def stringify_values
|
|
62
|
-
self.dup.stringify_values!
|
|
63
|
-
end
|
|
64
|
-
def stringify_values!
|
|
65
|
-
self.each_with_index { |v,i| self[i] = v.to_s }
|
|
66
|
-
self
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def only(*values)
|
|
70
|
-
self.dup.only!(*values)
|
|
71
|
-
end
|
|
72
|
-
def only!(*values)
|
|
73
|
-
values.flatten!
|
|
74
|
-
i = 0
|
|
75
|
-
while i <= length-1 do
|
|
76
|
-
self[i].is_one_of?(values) ? i += 1 : self.slice!(i)
|
|
77
|
-
end
|
|
78
|
-
self
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def order(*ordered)
|
|
82
|
-
self.dup.order!(*ordered)
|
|
83
|
-
end
|
|
84
|
-
def order!(*ordered)
|
|
85
|
-
self.replace(ordered.flatten!.only!(self))
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
class Hash
|
|
90
|
-
# Transform all the keys in the hash to CamelCase format.
|
|
91
|
-
def camelize_keys(specials={})
|
|
92
|
-
self.dup.camelize_keys!(specials)
|
|
93
|
-
end
|
|
94
|
-
def camelize_keys!(specials={})
|
|
95
|
-
self.each_key do |k|
|
|
96
|
-
self[specials.has_key?(k) ? specials[k] : k.camelize] = self.delete(k)
|
|
97
|
-
end
|
|
98
|
-
self
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def stringify_keys(specials={})
|
|
102
|
-
self.dup.stringify_keys!(specials)
|
|
103
|
-
end
|
|
104
|
-
def stringify_keys!(specials={})
|
|
105
|
-
self.each_key do |k|
|
|
106
|
-
self[specials.has_key?(k) ? specials[k] : k.to_s] = self.delete(k)
|
|
107
|
-
end
|
|
108
|
-
self
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def only(*keys)
|
|
112
|
-
self.dup.only!(*keys)
|
|
113
|
-
end
|
|
114
|
-
def only!(*keys)
|
|
115
|
-
keys = keys.flatten
|
|
116
|
-
self.keys.each { |k| self.delete(k) unless keys.include?(k) }
|
|
117
|
-
self
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def transform_keys(trans_hash)
|
|
121
|
-
self.dup.transform_keys!(trans_hash)
|
|
122
|
-
end
|
|
123
|
-
def transform_keys!(trans_hash)
|
|
124
|
-
raise ArgumentError, "transform_keys takes a single hash argument" unless trans_hash.is_a?(Hash)
|
|
125
|
-
self.each_key do |k|
|
|
126
|
-
self[trans_hash.has_key?(k) ? trans_hash[k] : k] = self.delete(k)
|
|
127
|
-
end
|
|
128
|
-
self
|
|
129
|
-
end
|
|
130
|
-
end
|