quickbooks 0.4.0 → 0.9.9

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