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
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require File.dirname(__FILE__)+'/duration'
|
|
2
|
+
class Numeric
|
|
3
|
+
def weeks
|
|
4
|
+
self == 1 ? Week.new : Weeks.new(self)
|
|
5
|
+
end
|
|
6
|
+
def week
|
|
7
|
+
self.weeks
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def days
|
|
11
|
+
self == 1 ? Day.new : Days.new(self)
|
|
12
|
+
end
|
|
13
|
+
def day
|
|
14
|
+
self.days
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def hours
|
|
18
|
+
self == 1 ? Hour.new : Hours.new(self)
|
|
19
|
+
end
|
|
20
|
+
def hour
|
|
21
|
+
self.hours
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def minutes
|
|
25
|
+
self == 1 ? Minute.new : Minutes.new(self)
|
|
26
|
+
end
|
|
27
|
+
def minute
|
|
28
|
+
self.minutes
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def seconds
|
|
32
|
+
self == 1 ? Second.new : Seconds.new(self)
|
|
33
|
+
end
|
|
34
|
+
def second
|
|
35
|
+
self.seconds
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def is_multiple_of?(num)
|
|
39
|
+
self % num == 0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def am
|
|
43
|
+
Time.parse("#{self}:00:00")
|
|
44
|
+
end
|
|
45
|
+
def pm
|
|
46
|
+
Time.parse("#{self+12}:00:00")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Object
|
|
2
|
+
def bind_class_object_method(other, self_method_name, other_method_name, args=[[],[]])
|
|
3
|
+
# Since I can't pass the 'other' object into eval as a string, I have to
|
|
4
|
+
# set a class instance variable and copy the contents to a class variable
|
|
5
|
+
# so that the generated method will play nicely with subclasses.
|
|
6
|
+
self.instance_variable_set("@#{self_method_name.to_s}_OBJ", other)
|
|
7
|
+
self.send :eval, "@@#{self_method_name.to_s}_OBJ = @#{self_method_name.to_s}_OBJ
|
|
8
|
+
def #{self_method_name.to_s}(#{args[0].join(', ')})
|
|
9
|
+
@@#{self_method_name.to_s}_OBJ.#{other_method_name.to_s}(#{args[1].join(', ')})
|
|
10
|
+
end"
|
|
11
|
+
self
|
|
12
|
+
end
|
|
13
|
+
def bind_object_method(other, self_method_name, other_method_name, args=[[],[]])
|
|
14
|
+
self.instance_variable_set("@#{self_method_name}_OBJ", other)
|
|
15
|
+
eval "def self.#{self_method_name}(#{args[0].join(', ')})
|
|
16
|
+
@#{self_method_name}_OBJ.#{other_method_name}(#{args[1].join(', ')})
|
|
17
|
+
end"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require 'time'
|
|
2
|
+
class Time
|
|
3
|
+
def to_time
|
|
4
|
+
self
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Returns a new Time where one or more of the elements have been changed according to the +options+ parameter. The time options
|
|
8
|
+
# (hour, minute, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and
|
|
9
|
+
# minute is passed, then sec and usec is set to 0.
|
|
10
|
+
def change(options)
|
|
11
|
+
::Time.send(
|
|
12
|
+
self.utc? ? :utc_time : :local_time,
|
|
13
|
+
options[:year] || self.year,
|
|
14
|
+
options[:month] || self.month,
|
|
15
|
+
options[:day] || options[:mday] || self.day, # mday is deprecated
|
|
16
|
+
options[:hour] || self.hour,
|
|
17
|
+
options[:min] || (options[:hour] ? 0 : self.min),
|
|
18
|
+
options[:sec] || ((options[:hour] || options[:min]) ? 0 : self.sec),
|
|
19
|
+
options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : self.usec)
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def day_name
|
|
24
|
+
self.strftime("%A")
|
|
25
|
+
end
|
|
26
|
+
def month_name
|
|
27
|
+
self.strftime("%B")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Seconds since midnight: Time.now.seconds_since_midnight
|
|
31
|
+
def seconds_since_midnight
|
|
32
|
+
self.to_i - self.change(:hour => 0).to_i + (self.usec/1.0e+6)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Returns a new Time representing the start of the day (0:00)
|
|
36
|
+
def beginning_of_day
|
|
37
|
+
(self - self.seconds_since_midnight).change(:usec => 0)
|
|
38
|
+
end
|
|
39
|
+
alias :midnight :beginning_of_day
|
|
40
|
+
alias :at_midnight :beginning_of_day
|
|
41
|
+
alias :at_beginning_of_day :beginning_of_day
|
|
42
|
+
|
|
43
|
+
# Returns a new Time if requested year can be accomodated by Ruby's Time class
|
|
44
|
+
# (i.e., if year is within either 1970..2038 or 1902..2038, depending on system architecture);
|
|
45
|
+
# otherwise returns a DateTime
|
|
46
|
+
def self.time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
|
|
47
|
+
::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
|
|
48
|
+
rescue
|
|
49
|
+
offset = if utc_or_local.to_sym == :utc then 0 else ::DateTime.now.offset end
|
|
50
|
+
::DateTime.civil(year, month, day, hour, min, sec, offset, 0)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# wraps class method time_with_datetime_fallback with utc_or_local == :utc
|
|
54
|
+
def self.utc_time(*args)
|
|
55
|
+
time_with_datetime_fallback(:utc, *args)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# wraps class method time_with_datetime_fallback with utc_or_local == :local
|
|
59
|
+
def self.local_time(*args)
|
|
60
|
+
time_with_datetime_fallback(:local, *args)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.tomorrow
|
|
64
|
+
Time.now.beginning_of_day + 1.day
|
|
65
|
+
end
|
|
66
|
+
def tomorrow
|
|
67
|
+
self.beginning_of_day + 1.day
|
|
68
|
+
end
|
|
69
|
+
def self.yesterday
|
|
70
|
+
Time.now.beginning_of_day - 1.day
|
|
71
|
+
end
|
|
72
|
+
def yesterday
|
|
73
|
+
self.beginning_of_day - 1.day
|
|
74
|
+
end
|
|
75
|
+
def self.today
|
|
76
|
+
Time.now.beginning_of_day
|
|
77
|
+
end
|
|
78
|
+
def self.next_month
|
|
79
|
+
today.change(:day => 1, :month => today.month + 1)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def until(end_time)
|
|
83
|
+
Duration.new(end_time - self, self)
|
|
84
|
+
end
|
|
85
|
+
def through(duration)
|
|
86
|
+
self.until(duration)
|
|
87
|
+
end
|
|
88
|
+
def for(duration)
|
|
89
|
+
raise TypeError, "must be a Duration object." unless duration.is_a?(Duration)
|
|
90
|
+
duration.start_time = self
|
|
91
|
+
duration
|
|
92
|
+
end
|
|
93
|
+
def is_today?
|
|
94
|
+
self.beginning_of_day == Time.today
|
|
95
|
+
end
|
|
96
|
+
def strfsql
|
|
97
|
+
self.strftime("%Y-#{self.strftime("%m").to_i.to_s}-#{self.strftime("%d").to_i.to_s}")
|
|
98
|
+
end
|
|
99
|
+
def self.from_tzid(tzid) #We aren't handling the Time Zone part here...
|
|
100
|
+
if tzid =~ /(\d\d\d\d)(\d\d)(\d\d)T(\d\d)(\d\d)(\d\d)Z/ # yyyymmddThhmmss
|
|
101
|
+
Time.xmlschema("#{$1}-#{$2}-#{$3}T#{$4}:#{$5}:#{$6}")
|
|
102
|
+
else
|
|
103
|
+
return nil
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
def humanize_time
|
|
107
|
+
self.strftime("%M").to_i > 0 ? self.strftime("#{self.strftime("%I").to_i.to_s}:%M%p").downcase : self.strftime("#{self.strftime("%I").to_i.to_s}%p").downcase
|
|
108
|
+
end
|
|
109
|
+
def humanize_date(length_profile='medium') #There may be decent reason to change how this works entirely...
|
|
110
|
+
case length_profile
|
|
111
|
+
when 'abbr' || 'abbreviated'
|
|
112
|
+
self.strftime("%m/%d/%y")
|
|
113
|
+
when 'short'
|
|
114
|
+
self.strftime("%b #{self.strftime("%d").to_i.to_s}")
|
|
115
|
+
when 'medium'
|
|
116
|
+
self.strftime("%B #{self.strftime("%d").to_i.to_s}")
|
|
117
|
+
when 'long'
|
|
118
|
+
self.strftime("%B #{self.strftime("%d").to_i.to_s}, %Y")
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
def humanize_date_time
|
|
122
|
+
self.humanize_date + ' ' + self.humanize_time
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def Today
|
|
127
|
+
Time.today
|
|
128
|
+
end
|
|
129
|
+
def Yesterday
|
|
130
|
+
Time.yesterday
|
|
131
|
+
end
|
|
132
|
+
def Tomorrow
|
|
133
|
+
Time.tomorrow
|
|
134
|
+
end
|
|
135
|
+
def Now
|
|
136
|
+
Time.now
|
|
137
|
+
end
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
class Hash
|
|
2
|
+
##
|
|
3
|
+
# Convert to URL query param string
|
|
4
|
+
#
|
|
5
|
+
# { :name => "Bob",
|
|
6
|
+
# :address => {
|
|
7
|
+
# :street => '111 Ruby Ave.',
|
|
8
|
+
# :city => 'Ruby Central',
|
|
9
|
+
# :phones => ['111-111-1111', '222-222-2222']
|
|
10
|
+
# }
|
|
11
|
+
# }.to_params
|
|
12
|
+
# #=> "name=Bob&address[city]=Ruby Central&address[phones][]=111-111-1111&address[phones][]=222-222-2222&address[street]=111 Ruby Ave."
|
|
13
|
+
#
|
|
14
|
+
# @return [String] This hash as a query string
|
|
15
|
+
#
|
|
16
|
+
# @api public
|
|
17
|
+
def to_params
|
|
18
|
+
params = self.map { |k,v| normalize_param(k,v) }.join
|
|
19
|
+
params.chop! # trailing &
|
|
20
|
+
params
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Convert a key, value pair into a URL query param string
|
|
25
|
+
#
|
|
26
|
+
# normalize_param(:name, "Bob") #=> "name=Bob&"
|
|
27
|
+
#
|
|
28
|
+
# @param [Object] key The key for the param.
|
|
29
|
+
# @param [Object] value The value for the param.
|
|
30
|
+
#
|
|
31
|
+
# @return <String> This key value pair as a param
|
|
32
|
+
#
|
|
33
|
+
# @api public
|
|
34
|
+
def normalize_param(key, value)
|
|
35
|
+
param = ''
|
|
36
|
+
stack = []
|
|
37
|
+
|
|
38
|
+
if value.is_a?(Array)
|
|
39
|
+
param << value.map { |element| normalize_param("#{key}[]", element) }.join
|
|
40
|
+
elsif value.is_a?(Hash)
|
|
41
|
+
stack << [key,value]
|
|
42
|
+
else
|
|
43
|
+
param << "#{key}=#{value}&"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
stack.each do |parent, hash|
|
|
47
|
+
hash.each do |key, value|
|
|
48
|
+
if value.is_a?(Hash)
|
|
49
|
+
stack << ["#{parent}[#{key}]", value]
|
|
50
|
+
else
|
|
51
|
+
param << normalize_param("#{parent}[#{key}]", value)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
param
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
##
|
|
60
|
+
# Create a hash with *only* key/value pairs in receiver and +allowed+
|
|
61
|
+
#
|
|
62
|
+
# { :one => 1, :two => 2, :three => 3 }.only(:one) #=> { :one => 1 }
|
|
63
|
+
#
|
|
64
|
+
# @param [Array[String, Symbol]] *allowed The hash keys to include.
|
|
65
|
+
#
|
|
66
|
+
# @return [Hash] A new hash with only the selected keys.
|
|
67
|
+
#
|
|
68
|
+
# @api public
|
|
69
|
+
def only(*allowed)
|
|
70
|
+
hash = {}
|
|
71
|
+
allowed.each {|k| hash[k] = self[k] if self.has_key?(k) }
|
|
72
|
+
hash
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
##
|
|
76
|
+
# Create a hash with all key/value pairs in receiver *except* +rejected+
|
|
77
|
+
#
|
|
78
|
+
# { :one => 1, :two => 2, :three => 3 }.except(:one)
|
|
79
|
+
# #=> { :two => 2, :three => 3 }
|
|
80
|
+
#
|
|
81
|
+
# @param [Array[String, Symbol]] *rejected The hash keys to exclude.
|
|
82
|
+
#
|
|
83
|
+
# @return [Hash] A new hash without the selected keys.
|
|
84
|
+
#
|
|
85
|
+
# @api public
|
|
86
|
+
def except(*rejected)
|
|
87
|
+
hash = self.dup
|
|
88
|
+
rejected.each {|k| hash.delete(k) }
|
|
89
|
+
hash
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# @return <String> The hash as attributes for an XML tag.
|
|
93
|
+
#
|
|
94
|
+
# @example
|
|
95
|
+
# { :one => 1, "two"=>"TWO" }.to_xml_attributes
|
|
96
|
+
# #=> 'one="1" two="TWO"'
|
|
97
|
+
def to_xml_attributes
|
|
98
|
+
map do |k,v|
|
|
99
|
+
%{#{k.to_s.snake_case.sub(/^(.{1,1})/) { |m| m.downcase }}="#{v}"}
|
|
100
|
+
end.join(' ')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
alias_method :to_html_attributes, :to_xml_attributes
|
|
104
|
+
|
|
105
|
+
# @param html_class<#to_s>
|
|
106
|
+
# The HTML class to add to the :class key. The html_class will be
|
|
107
|
+
# concatenated to any existing classes.
|
|
108
|
+
#
|
|
109
|
+
# @example hash[:class] #=> nil
|
|
110
|
+
# @example hash.add_html_class!(:selected)
|
|
111
|
+
# @example hash[:class] #=> "selected"
|
|
112
|
+
# @example hash.add_html_class!("class1 class2")
|
|
113
|
+
# @example hash[:class] #=> "selected class1 class2"
|
|
114
|
+
def add_html_class!(html_class)
|
|
115
|
+
if self[:class]
|
|
116
|
+
self[:class] = "#{self[:class]} #{html_class}"
|
|
117
|
+
else
|
|
118
|
+
self[:class] = html_class.to_s
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Converts all keys into string values. This is used during reloading to
|
|
123
|
+
# prevent problems when classes are no longer declared.
|
|
124
|
+
#
|
|
125
|
+
# @return <Array> An array of they hash's keys
|
|
126
|
+
#
|
|
127
|
+
# @example
|
|
128
|
+
# hash = { One => 1, Two => 2 }.proctect_keys!
|
|
129
|
+
# hash # => { "One" => 1, "Two" => 2 }
|
|
130
|
+
def protect_keys!
|
|
131
|
+
keys.each {|key| self[key.to_s] = delete(key) }
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Attempts to convert all string keys into Class keys. We run this after
|
|
135
|
+
# reloading to convert protected hashes back into usable hashes.
|
|
136
|
+
#
|
|
137
|
+
# @example
|
|
138
|
+
# # Provided that classes One and Two are declared in this scope:
|
|
139
|
+
# hash = { "One" => 1, "Two" => 2 }.unproctect_keys!
|
|
140
|
+
# hash # => { One => 1, Two => 2 }
|
|
141
|
+
def unprotect_keys!
|
|
142
|
+
keys.each do |key|
|
|
143
|
+
(self[Object.full_const_get(key)] = delete(key)) rescue nil
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Destructively and non-recursively convert each key to an uppercase string,
|
|
148
|
+
# deleting nil values along the way.
|
|
149
|
+
#
|
|
150
|
+
# @return <Hash> The newly environmentized hash.
|
|
151
|
+
#
|
|
152
|
+
# @example
|
|
153
|
+
# { :name => "Bob", :contact => { :email => "bob@bob.com" } }.environmentize_keys!
|
|
154
|
+
# #=> { "NAME" => "Bob", "CONTACT" => { :email => "bob@bob.com" } }
|
|
155
|
+
def environmentize_keys!
|
|
156
|
+
keys.each do |key|
|
|
157
|
+
val = delete(key)
|
|
158
|
+
next if val.nil?
|
|
159
|
+
self[key.to_s.upcase] = val
|
|
160
|
+
end
|
|
161
|
+
self
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
require 'rexml/parsers/streamparser'
|
|
166
|
+
require 'rexml/parsers/baseparser'
|
|
167
|
+
require 'rexml/light/node'
|
|
168
|
+
|
|
169
|
+
# This is a slighly modified version of the XMLUtilityNode from
|
|
170
|
+
# http://merb.devjavu.com/projects/merb/ticket/95 (has.sox@gmail.com)
|
|
171
|
+
# It's mainly just adding vowels, as I ht cd wth n vwls :)
|
|
172
|
+
# This represents the hard part of the work, all I did was change the
|
|
173
|
+
# underlying parser.
|
|
174
|
+
class REXMLUtilityNode
|
|
175
|
+
attr_accessor :name, :attributes, :children, :type
|
|
176
|
+
cattr_accessor :typecasts, :available_typecasts
|
|
177
|
+
|
|
178
|
+
self.typecasts = {}
|
|
179
|
+
self.typecasts["integer"] = lambda{|v| v.nil? ? nil : v.to_i}
|
|
180
|
+
self.typecasts["boolean"] = lambda{|v| v.nil? ? nil : (v.strip != "false")}
|
|
181
|
+
self.typecasts["datetime"] = lambda{|v| v.nil? ? nil : Time.parse(v).utc}
|
|
182
|
+
self.typecasts["date"] = lambda{|v| v.nil? ? nil : Date.parse(v)}
|
|
183
|
+
self.typecasts["dateTime"] = lambda{|v| v.nil? ? nil : Time.parse(v).utc}
|
|
184
|
+
self.typecasts["decimal"] = lambda{|v| BigDecimal(v)}
|
|
185
|
+
self.typecasts["double"] = lambda{|v| v.nil? ? nil : v.to_f}
|
|
186
|
+
self.typecasts["float"] = lambda{|v| v.nil? ? nil : v.to_f}
|
|
187
|
+
self.typecasts["symbol"] = lambda{|v| v.to_sym}
|
|
188
|
+
self.typecasts["string"] = lambda{|v| v.to_s}
|
|
189
|
+
self.typecasts["yaml"] = lambda{|v| v.nil? ? nil : YAML.load(v)}
|
|
190
|
+
self.typecasts["base64Binary"] = lambda{|v| v.unpack('m').first }
|
|
191
|
+
|
|
192
|
+
self.available_typecasts = self.typecasts.keys
|
|
193
|
+
|
|
194
|
+
def initialize(name, attributes = {})
|
|
195
|
+
@name = name.tr("-", "_")
|
|
196
|
+
# leave the type alone if we don't know what it is
|
|
197
|
+
@type = self.class.available_typecasts.include?(attributes["type"]) ? attributes.delete("type") : attributes["type"]
|
|
198
|
+
|
|
199
|
+
@nil_element = attributes.delete("nil") == "true"
|
|
200
|
+
@attributes = undasherize_keys(attributes)
|
|
201
|
+
@children = []
|
|
202
|
+
@text = false
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def add_node(node)
|
|
206
|
+
@text = true if node.is_a? String
|
|
207
|
+
@children << node
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def to_hash
|
|
211
|
+
if @type == "file"
|
|
212
|
+
f = StringIO.new((@children.first || '').unpack('m').first)
|
|
213
|
+
class << f
|
|
214
|
+
attr_accessor :original_filename, :content_type
|
|
215
|
+
end
|
|
216
|
+
f.original_filename = attributes['name'] || 'untitled'
|
|
217
|
+
f.content_type = attributes['content_type'] || 'application/octet-stream'
|
|
218
|
+
return {name => f}
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
if @text
|
|
222
|
+
return { name => typecast_value( translate_xml_entities( inner_html ) ) }
|
|
223
|
+
else
|
|
224
|
+
#change repeating groups into an array
|
|
225
|
+
groups = @children.inject({}) { |s,e| (s[e.name] ||= []) << e; s }
|
|
226
|
+
|
|
227
|
+
out = nil
|
|
228
|
+
if @type == "array"
|
|
229
|
+
out = []
|
|
230
|
+
groups.each do |k, v|
|
|
231
|
+
if v.size == 1
|
|
232
|
+
out << v.first.to_hash.entries.first.last
|
|
233
|
+
else
|
|
234
|
+
out << v.map{|e| e.to_hash[k]}
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
out = out.flatten
|
|
238
|
+
|
|
239
|
+
else # If Hash
|
|
240
|
+
out = {}
|
|
241
|
+
groups.each do |k,v|
|
|
242
|
+
if v.size == 1
|
|
243
|
+
out.merge!(v.first)
|
|
244
|
+
else
|
|
245
|
+
out.merge!( k => v.map{|e| e.to_hash[k]})
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
out.merge! attributes unless attributes.empty?
|
|
249
|
+
out = out.empty? ? nil : out
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
if @type && out.nil?
|
|
253
|
+
{ name => typecast_value(out) }
|
|
254
|
+
else
|
|
255
|
+
{ name => out }
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Typecasts a value based upon its type. For instance, if
|
|
261
|
+
# +node+ has #type == "integer",
|
|
262
|
+
# {{[node.typecast_value("12") #=> 12]}}
|
|
263
|
+
#
|
|
264
|
+
# @param value<String> The value that is being typecast.
|
|
265
|
+
#
|
|
266
|
+
# @details [:type options]
|
|
267
|
+
# "integer"::
|
|
268
|
+
# converts +value+ to an integer with #to_i
|
|
269
|
+
# "boolean"::
|
|
270
|
+
# checks whether +value+, after removing spaces, is the literal
|
|
271
|
+
# "true"
|
|
272
|
+
# "datetime"::
|
|
273
|
+
# Parses +value+ using Time.parse, and returns a UTC Time
|
|
274
|
+
# "date"::
|
|
275
|
+
# Parses +value+ using Date.parse
|
|
276
|
+
#
|
|
277
|
+
# @return <Integer, TrueClass, FalseClass, Time, Date, Object>
|
|
278
|
+
# The result of typecasting +value+.
|
|
279
|
+
#
|
|
280
|
+
# @note
|
|
281
|
+
# If +self+ does not have a "type" key, or if it's not one of the
|
|
282
|
+
# options specified above, the raw +value+ will be returned.
|
|
283
|
+
def typecast_value(value)
|
|
284
|
+
return value unless @type
|
|
285
|
+
proc = self.class.typecasts[@type]
|
|
286
|
+
proc.nil? ? value : proc.call(value)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Convert basic XML entities into their literal values.
|
|
290
|
+
#
|
|
291
|
+
# @param value<#gsub> An XML fragment.
|
|
292
|
+
#
|
|
293
|
+
# @return <#gsub> The XML fragment after converting entities.
|
|
294
|
+
def translate_xml_entities(value)
|
|
295
|
+
value.gsub(/</, "<").
|
|
296
|
+
gsub(/>/, ">").
|
|
297
|
+
gsub(/"/, '"').
|
|
298
|
+
gsub(/'/, "'").
|
|
299
|
+
gsub(/&/, "&")
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# Take keys of the form foo-bar and convert them to foo_bar
|
|
303
|
+
def undasherize_keys(params)
|
|
304
|
+
params.keys.each do |key, value|
|
|
305
|
+
params[key.tr("-", "_")] = params.delete(key)
|
|
306
|
+
end
|
|
307
|
+
params
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Get the inner_html of the REXML node.
|
|
311
|
+
def inner_html
|
|
312
|
+
@children.join
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Converts the node into a readable HTML node.
|
|
316
|
+
#
|
|
317
|
+
# @return <String> The HTML node in text form.
|
|
318
|
+
def to_html
|
|
319
|
+
attributes.merge!(:type => @type ) if @type
|
|
320
|
+
"<#{name}#{attributes.to_xml_attributes}>#{@nil_element ? '' : inner_html}</#{name}>"
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# @alias #to_html #to_s
|
|
324
|
+
def to_s
|
|
325
|
+
to_html
|
|
326
|
+
end
|
|
327
|
+
end
|