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.
Files changed (293) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +23 -0
  3. data/License.txt +54 -0
  4. data/Manifest.txt +73 -0
  5. data/README.txt +79 -0
  6. data/Rakefile +17 -78
  7. data/lib/quickbooks.rb +153 -7
  8. data/lib/quickbooks/adaptability.rb +67 -0
  9. data/lib/quickbooks/adapters/http_adapter.rb +94 -0
  10. data/lib/quickbooks/adapters/https_adapter.rb +57 -0
  11. data/lib/quickbooks/adapters/ole_adapter.rb +141 -110
  12. data/lib/quickbooks/adapters/spew_adapter.rb +39 -0
  13. data/lib/quickbooks/adapters/tcp_adapter.rb +71 -0
  14. data/lib/quickbooks/adapters/test_adapter.rb +62 -0
  15. data/lib/quickbooks/element.rb +385 -0
  16. data/lib/quickbooks/element_collection.rb +105 -0
  17. data/lib/quickbooks/extlib.rb +8 -0
  18. data/lib/quickbooks/extlib/assertions.rb +8 -0
  19. data/lib/quickbooks/extlib/class.rb +98 -0
  20. data/lib/quickbooks/extlib/days_and_times.rb +10 -0
  21. data/lib/quickbooks/extlib/days_and_times/duration.rb +362 -0
  22. data/lib/quickbooks/extlib/days_and_times/numeric.rb +48 -0
  23. data/lib/quickbooks/extlib/days_and_times/object.rb +19 -0
  24. data/lib/quickbooks/extlib/days_and_times/time.rb +137 -0
  25. data/lib/quickbooks/extlib/hash.rb +327 -0
  26. data/lib/quickbooks/extlib/hook.rb +366 -0
  27. data/lib/quickbooks/extlib/inflection.rb +436 -0
  28. data/lib/quickbooks/extlib/logger.rb +202 -0
  29. data/lib/quickbooks/extlib/object.rb +162 -0
  30. data/lib/quickbooks/extlib/pathname.rb +15 -0
  31. data/lib/quickbooks/extlib/rubygems.rb +38 -0
  32. data/lib/quickbooks/extlib/string.rb +32 -0
  33. data/lib/quickbooks/extlib/time.rb +41 -0
  34. data/lib/quickbooks/model.rb +503 -121
  35. data/lib/quickbooks/option.rb +95 -0
  36. data/lib/quickbooks/property.rb +69 -0
  37. data/lib/quickbooks/ruby_ext.rb +251 -0
  38. data/lib/quickbooks/type.rb +75 -0
  39. data/lib/quickbooks/types.rb +58 -0
  40. data/lib/quickbooks/version.rb +10 -0
  41. data/lib/quickbooks/xsd.rb +243 -0
  42. data/lib/quickbooks/xsd/attribute.rb +57 -0
  43. data/lib/quickbooks/xsd/choice.rb +94 -0
  44. data/lib/quickbooks/xsd/complex_type.rb +77 -0
  45. data/lib/quickbooks/xsd/element.rb +214 -0
  46. data/lib/quickbooks/xsd/group.rb +94 -0
  47. data/lib/quickbooks/xsd/restriction.rb +51 -0
  48. data/lib/quickbooks/xsd/sequence.rb +85 -0
  49. data/lib/quickbooks/xsd/simple_type.rb +87 -0
  50. data/lib/quickbooks/xsd/union.rb +70 -0
  51. data/lib/quickbooks/xsd/validation.rb +89 -0
  52. data/lib/quickbooks/xsd/xml_parse.rb +80 -0
  53. data/quickbooks.gemspec +36 -0
  54. data/source/qbxml21_demo.xsd +2223 -0
  55. data/source/qbxmlops_demo.xsd +483 -0
  56. data/source/qbxmltypes.xsd +160 -0
  57. data/spec/association_spec.rb +5 -0
  58. data/spec/element_collection_spec.rb +8 -0
  59. data/spec/find_spec.rb +30 -0
  60. data/spec/lib/quickbooks/element_spec.rb +83 -0
  61. data/spec/lib/quickbooks/elements/sales_order_add_spec.rb +14 -0
  62. data/spec/lib/quickbooks/elements/vendor_add_spec.rb +78 -0
  63. data/spec/lib/quickbooks/model_spec.rb +89 -0
  64. data/spec/lib/quickbooks/models/customer_spec.rb +52 -0
  65. data/spec/lib/quickbooks/models/invoice_spec.rb +12 -0
  66. data/spec/lib/quickbooks/models/sales_order_line_spec.rb +0 -0
  67. data/spec/lib/quickbooks/models/sales_order_spec.rb +145 -0
  68. data/spec/lib/quickbooks/xsd/choice_spec.rb +18 -0
  69. data/spec/pending_spec.rb +11 -0
  70. data/spec/quickbooks_spec.rb +38 -0
  71. data/spec/repeatable_spec.rb +20 -0
  72. data/spec/requires_spec.rb +10 -0
  73. data/spec/spec_helper.rb +5 -0
  74. data/spec/validation_spec.rb +24 -0
  75. metadata +133 -285
  76. metadata.gz.sig +0 -0
  77. data/LICENSE +0 -16
  78. data/README +0 -49
  79. data/doc/classes/Array.html +0 -368
  80. data/doc/classes/Array.src/M000026.html +0 -18
  81. data/doc/classes/Array.src/M000027.html +0 -21
  82. data/doc/classes/Array.src/M000028.html +0 -18
  83. data/doc/classes/Array.src/M000029.html +0 -19
  84. data/doc/classes/Array.src/M000030.html +0 -18
  85. data/doc/classes/Array.src/M000031.html +0 -23
  86. data/doc/classes/Array.src/M000032.html +0 -18
  87. data/doc/classes/Array.src/M000033.html +0 -18
  88. data/doc/classes/Array.src/M000034.html +0 -18
  89. data/doc/classes/Array.src/M000035.html +0 -19
  90. data/doc/classes/Array.src/M000036.html +0 -18
  91. data/doc/classes/Array.src/M000037.html +0 -23
  92. data/doc/classes/Array.src/M000038.html +0 -18
  93. data/doc/classes/Array.src/M000039.html +0 -21
  94. data/doc/classes/Array.src/M000040.html +0 -18
  95. data/doc/classes/Array.src/M000041.html +0 -18
  96. data/doc/classes/Class.html +0 -171
  97. data/doc/classes/Class.src/M000042.html +0 -18
  98. data/doc/classes/Class.src/M000043.html +0 -18
  99. data/doc/classes/Hash.html +0 -516
  100. data/doc/classes/Hash.src/M000001.html +0 -18
  101. data/doc/classes/Hash.src/M000002.html +0 -21
  102. data/doc/classes/Hash.src/M000003.html +0 -18
  103. data/doc/classes/Hash.src/M000004.html +0 -21
  104. data/doc/classes/Hash.src/M000005.html +0 -18
  105. data/doc/classes/Hash.src/M000006.html +0 -20
  106. data/doc/classes/Hash.src/M000007.html +0 -18
  107. data/doc/classes/Hash.src/M000008.html +0 -22
  108. data/doc/classes/Hash.src/M000009.html +0 -18
  109. data/doc/classes/Hash.src/M000010.html +0 -21
  110. data/doc/classes/Hash.src/M000011.html +0 -24
  111. data/doc/classes/Hash.src/M000012.html +0 -18
  112. data/doc/classes/Hash.src/M000013.html +0 -21
  113. data/doc/classes/Hash.src/M000014.html +0 -18
  114. data/doc/classes/Hash.src/M000015.html +0 -21
  115. data/doc/classes/Hash.src/M000016.html +0 -18
  116. data/doc/classes/Hash.src/M000017.html +0 -21
  117. data/doc/classes/Hash.src/M000018.html +0 -27
  118. data/doc/classes/Hash.src/M000019.html +0 -20
  119. data/doc/classes/Hash.src/M000020.html +0 -18
  120. data/doc/classes/Hash.src/M000021.html +0 -18
  121. data/doc/classes/Hash.src/M000022.html +0 -18
  122. data/doc/classes/Hash.src/M000023.html +0 -18
  123. data/doc/classes/Hash.src/M000024.html +0 -18
  124. data/doc/classes/Hash.src/M000025.html +0 -28
  125. data/doc/classes/Object.html +0 -278
  126. data/doc/classes/Object.src/M000044.html +0 -24
  127. data/doc/classes/Object.src/M000045.html +0 -19
  128. data/doc/classes/Object.src/M000046.html +0 -24
  129. data/doc/classes/Object.src/M000047.html +0 -18
  130. data/doc/classes/Object.src/M000048.html +0 -19
  131. data/doc/classes/Object.src/M000049.html +0 -18
  132. data/doc/classes/Object.src/M000050.html +0 -18
  133. data/doc/classes/Object.src/M000051.html +0 -18
  134. data/doc/classes/Qbxml.html +0 -131
  135. data/doc/classes/Qbxml/Request.html +0 -224
  136. data/doc/classes/Qbxml/Request.src/M000132.html +0 -66
  137. data/doc/classes/Qbxml/Request.src/M000133.html +0 -19
  138. data/doc/classes/Qbxml/Request.src/M000134.html +0 -83
  139. data/doc/classes/Qbxml/RequestSet.html +0 -199
  140. data/doc/classes/Qbxml/RequestSet.src/M000135.html +0 -22
  141. data/doc/classes/Qbxml/RequestSet.src/M000136.html +0 -26
  142. data/doc/classes/Qbxml/RequestSet.src/M000137.html +0 -18
  143. data/doc/classes/Qbxml/RequestSet.src/M000138.html +0 -22
  144. data/doc/classes/Qbxml/Response.html +0 -302
  145. data/doc/classes/Qbxml/Response.src/M000123.html +0 -24
  146. data/doc/classes/Qbxml/Response.src/M000124.html +0 -19
  147. data/doc/classes/Qbxml/Response.src/M000125.html +0 -55
  148. data/doc/classes/Qbxml/Response.src/M000126.html +0 -18
  149. data/doc/classes/Qbxml/Response.src/M000127.html +0 -18
  150. data/doc/classes/Qbxml/Response.src/M000128.html +0 -18
  151. data/doc/classes/Qbxml/Response.src/M000129.html +0 -18
  152. data/doc/classes/Qbxml/Response.src/M000130.html +0 -18
  153. data/doc/classes/Qbxml/Response.src/M000131.html +0 -63
  154. data/doc/classes/Qbxml/ResponseSet.html +0 -244
  155. data/doc/classes/Qbxml/ResponseSet.src/M000116.html +0 -22
  156. data/doc/classes/Qbxml/ResponseSet.src/M000117.html +0 -26
  157. data/doc/classes/Qbxml/ResponseSet.src/M000118.html +0 -24
  158. data/doc/classes/Qbxml/ResponseSet.src/M000119.html +0 -20
  159. data/doc/classes/Qbxml/ResponseSet.src/M000120.html +0 -27
  160. data/doc/classes/Qbxml/ResponseSet.src/M000121.html +0 -18
  161. data/doc/classes/Qbxml/ResponseSet.src/M000122.html +0 -18
  162. data/doc/classes/Quickbooks.html +0 -196
  163. data/doc/classes/Quickbooks/Address.html +0 -139
  164. data/doc/classes/Quickbooks/Address.src/M000115.html +0 -19
  165. data/doc/classes/Quickbooks/Base.html +0 -567
  166. data/doc/classes/Quickbooks/Base.src/M000095.html +0 -18
  167. data/doc/classes/Quickbooks/Base.src/M000096.html +0 -20
  168. data/doc/classes/Quickbooks/Base.src/M000097.html +0 -19
  169. data/doc/classes/Quickbooks/Base.src/M000098.html +0 -18
  170. data/doc/classes/Quickbooks/Base.src/M000099.html +0 -19
  171. data/doc/classes/Quickbooks/Base.src/M000100.html +0 -30
  172. data/doc/classes/Quickbooks/Base.src/M000101.html +0 -22
  173. data/doc/classes/Quickbooks/Base.src/M000102.html +0 -30
  174. data/doc/classes/Quickbooks/Base.src/M000103.html +0 -19
  175. data/doc/classes/Quickbooks/Base.src/M000104.html +0 -19
  176. data/doc/classes/Quickbooks/Base.src/M000105.html +0 -18
  177. data/doc/classes/Quickbooks/Base.src/M000106.html +0 -18
  178. data/doc/classes/Quickbooks/Base.src/M000107.html +0 -19
  179. data/doc/classes/Quickbooks/Base.src/M000108.html +0 -18
  180. data/doc/classes/Quickbooks/Base.src/M000109.html +0 -45
  181. data/doc/classes/Quickbooks/Base.src/M000110.html +0 -18
  182. data/doc/classes/Quickbooks/Base.src/M000111.html +0 -18
  183. data/doc/classes/Quickbooks/Base.src/M000112.html +0 -20
  184. data/doc/classes/Quickbooks/BillAddress.html +0 -113
  185. data/doc/classes/Quickbooks/CreditCardInfo.html +0 -113
  186. data/doc/classes/Quickbooks/Customer.html +0 -113
  187. data/doc/classes/Quickbooks/CustomerTypeRef.html +0 -113
  188. data/doc/classes/Quickbooks/Deleted.html +0 -113
  189. data/doc/classes/Quickbooks/ItemSalesTaxRef.html +0 -113
  190. data/doc/classes/Quickbooks/JobTypeRef.html +0 -113
  191. data/doc/classes/Quickbooks/ListDeleted.html +0 -139
  192. data/doc/classes/Quickbooks/ListDeleted.src/M000114.html +0 -18
  193. data/doc/classes/Quickbooks/ListItem.html +0 -170
  194. data/doc/classes/Quickbooks/ListItem.src/M000093.html +0 -20
  195. data/doc/classes/Quickbooks/ListItem.src/M000094.html +0 -18
  196. data/doc/classes/Quickbooks/Model.html +0 -462
  197. data/doc/classes/Quickbooks/Model.src/M000073.html +0 -24
  198. data/doc/classes/Quickbooks/Model.src/M000074.html +0 -19
  199. data/doc/classes/Quickbooks/Model.src/M000075.html +0 -18
  200. data/doc/classes/Quickbooks/Model.src/M000076.html +0 -18
  201. data/doc/classes/Quickbooks/Model.src/M000077.html +0 -18
  202. data/doc/classes/Quickbooks/Model.src/M000078.html +0 -22
  203. data/doc/classes/Quickbooks/Model.src/M000079.html +0 -32
  204. data/doc/classes/Quickbooks/Model.src/M000080.html +0 -32
  205. data/doc/classes/Quickbooks/Model.src/M000081.html +0 -18
  206. data/doc/classes/Quickbooks/Model.src/M000082.html +0 -18
  207. data/doc/classes/Quickbooks/Model.src/M000083.html +0 -22
  208. data/doc/classes/Quickbooks/Model.src/M000084.html +0 -23
  209. data/doc/classes/Quickbooks/Model.src/M000085.html +0 -18
  210. data/doc/classes/Quickbooks/Model.src/M000086.html +0 -21
  211. data/doc/classes/Quickbooks/Model.src/M000087.html +0 -26
  212. data/doc/classes/Quickbooks/Model.src/M000088.html +0 -26
  213. data/doc/classes/Quickbooks/Model.src/M000089.html +0 -26
  214. data/doc/classes/Quickbooks/Model.src/M000090.html +0 -21
  215. data/doc/classes/Quickbooks/Model.src/M000091.html +0 -23
  216. data/doc/classes/Quickbooks/OleAdapter.html +0 -129
  217. data/doc/classes/Quickbooks/OleAdapter/Connection.html +0 -343
  218. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000058.html +0 -18
  219. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000059.html +0 -19
  220. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000060.html +0 -24
  221. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000061.html +0 -18
  222. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000062.html +0 -18
  223. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000063.html +0 -21
  224. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000064.html +0 -24
  225. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000065.html +0 -20
  226. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000066.html +0 -24
  227. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000067.html +0 -24
  228. data/doc/classes/Quickbooks/OleAdapter/Ole.html +0 -209
  229. data/doc/classes/Quickbooks/OleAdapter/Ole.src/M000068.html +0 -21
  230. data/doc/classes/Quickbooks/OleAdapter/Ole.src/M000069.html +0 -22
  231. data/doc/classes/Quickbooks/OleAdapter/Ole.src/M000070.html +0 -18
  232. data/doc/classes/Quickbooks/ParentRef.html +0 -113
  233. data/doc/classes/Quickbooks/PreferredPaymentMethodRef.html +0 -113
  234. data/doc/classes/Quickbooks/PriceLevelRef.html +0 -113
  235. data/doc/classes/Quickbooks/QbxmlDebugAdapter.html +0 -111
  236. data/doc/classes/Quickbooks/QbxmlDebugAdapter/Connection.html +0 -139
  237. data/doc/classes/Quickbooks/QbxmlDebugAdapter/Connection.src/M000057.html +0 -18
  238. data/doc/classes/Quickbooks/Ref.html +0 -146
  239. data/doc/classes/Quickbooks/Ref.src/M000113.html +0 -18
  240. data/doc/classes/Quickbooks/SalesRepRef.html +0 -113
  241. data/doc/classes/Quickbooks/SalesTaxCodeRef.html +0 -113
  242. data/doc/classes/Quickbooks/ShipAddress.html +0 -113
  243. data/doc/classes/Quickbooks/TermsRef.html +0 -113
  244. data/doc/classes/Quickbooks/Transaction.html +0 -154
  245. data/doc/classes/Quickbooks/Transaction.src/M000071.html +0 -19
  246. data/doc/classes/Quickbooks/Transaction.src/M000072.html +0 -18
  247. data/doc/classes/Quickbooks/TxnDeleted.html +0 -139
  248. data/doc/classes/Quickbooks/TxnDeleted.src/M000092.html +0 -18
  249. data/doc/classes/String.html +0 -203
  250. data/doc/classes/String.src/M000052.html +0 -18
  251. data/doc/classes/String.src/M000053.html +0 -18
  252. data/doc/classes/String.src/M000054.html +0 -18
  253. data/doc/classes/String.src/M000055.html +0 -18
  254. data/doc/classes/String.src/M000056.html +0 -18
  255. data/doc/created.rid +0 -1
  256. data/doc/files/LICENSE.html +0 -129
  257. data/doc/files/README.html +0 -225
  258. data/doc/files/lib/qbxml/request_rb.html +0 -110
  259. data/doc/files/lib/qbxml/response_rb.html +0 -109
  260. data/doc/files/lib/qbxml/support_rb.html +0 -101
  261. data/doc/files/lib/qbxml_rb.html +0 -122
  262. data/doc/files/lib/quickbooks/adapters/ole_adapter_rb.html +0 -108
  263. data/doc/files/lib/quickbooks/adapters/qbxml_debug_adapter_rb.html +0 -108
  264. data/doc/files/lib/quickbooks/base_rb.html +0 -327
  265. data/doc/files/lib/quickbooks/model_rb.html +0 -108
  266. data/doc/files/lib/quickbooks/models/common/address_rb.html +0 -101
  267. data/doc/files/lib/quickbooks/models/common/all_refs_rb.html +0 -101
  268. data/doc/files/lib/quickbooks/models/customer/credit_card_info_rb.html +0 -101
  269. data/doc/files/lib/quickbooks/models/customer_rb.html +0 -110
  270. data/doc/files/lib/quickbooks/models/deleted_rb.html +0 -101
  271. data/doc/files/lib/quickbooks/models/list_item_rb.html +0 -101
  272. data/doc/files/lib/quickbooks/models/transaction_rb.html +0 -101
  273. data/doc/files/lib/quickbooks/ruby_magic_rb.html +0 -120
  274. data/doc/files/lib/quickbooks_rb.html +0 -125
  275. data/doc/fr_class_index.html +0 -64
  276. data/doc/fr_file_index.html +0 -45
  277. data/doc/fr_method_index.html +0 -164
  278. data/doc/index.html +0 -24
  279. data/doc/rdoc-style.css +0 -208
  280. data/lib/qbxml.rb +0 -3
  281. data/lib/qbxml/request.rb +0 -207
  282. data/lib/qbxml/response.rb +0 -197
  283. data/lib/qbxml/support.rb +0 -130
  284. data/lib/quickbooks/adapters/qbxml_debug_adapter.rb +0 -10
  285. data/lib/quickbooks/base.rb +0 -277
  286. data/lib/quickbooks/models/common/address.rb +0 -14
  287. data/lib/quickbooks/models/common/all_refs.rb +0 -37
  288. data/lib/quickbooks/models/customer.rb +0 -70
  289. data/lib/quickbooks/models/customer/credit_card_info.rb +0 -5
  290. data/lib/quickbooks/models/deleted.rb +0 -22
  291. data/lib/quickbooks/models/list_item.rb +0 -41
  292. data/lib/quickbooks/models/transaction.rb +0 -49
  293. 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(/&lt;/, "<").
296
+ gsub(/&gt;/, ">").
297
+ gsub(/&quot;/, '"').
298
+ gsub(/&apos;/, "'").
299
+ gsub(/&amp;/, "&")
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