quickbooks 0.4.0 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|