ipp_quickbase_devkit 0.0.1

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 (239) hide show
  1. data/LICENSE +87 -0
  2. data/README.rdoc +112 -0
  3. data/doc/QuickBaseClient.rb.htm +1896 -0
  4. data/doc/ReleaseNotes.txt +43 -0
  5. data/doc/qbc.makeCSVFile.qbc +4 -0
  6. data/doc/qbc.makeCSVFile.rb +4 -0
  7. data/doc/quickbase_adapter.rb.htm +399 -0
  8. data/examples/cookbookfiles/QuickBaseAPICookbook.html +2590 -0
  9. data/examples/cookbookfiles/addChangeRemoveUserRole.rb +21 -0
  10. data/examples/cookbookfiles/addOrEditRecord.rb +10 -0
  11. data/examples/cookbookfiles/application_object.rb +55 -0
  12. data/examples/cookbookfiles/applyRubyFormulas.rb +10 -0
  13. data/examples/cookbookfiles/average.rb +27 -0
  14. data/examples/cookbookfiles/backupApplication.rb +8 -0
  15. data/examples/cookbookfiles/cacheSchemas.rb +53 -0
  16. data/examples/cookbookfiles/calculateRunningTotals.rb +11 -0
  17. data/examples/cookbookfiles/copyrecords.rb +73 -0
  18. data/examples/cookbookfiles/count.rb +26 -0
  19. data/examples/cookbookfiles/createRecordNavigatorHTML.rb +42 -0
  20. data/examples/cookbookfiles/createReportDashboard.rb +35 -0
  21. data/examples/cookbookfiles/createTable.rb +12 -0
  22. data/examples/cookbookfiles/deviation.rb +25 -0
  23. data/examples/cookbookfiles/downloadCookbook.rb +97 -0
  24. data/examples/cookbookfiles/downloadFile.rb +10 -0
  25. data/examples/cookbookfiles/downloadFilesToFolder.rb +81 -0
  26. data/examples/cookbookfiles/downloadToTextFile.rb +64 -0
  27. data/examples/cookbookfiles/dumpSchema.rb +11 -0
  28. data/examples/cookbookfiles/duplicateRecord.rb +8 -0
  29. data/examples/cookbookfiles/dynamicMethods.rb +33 -0
  30. data/examples/cookbookfiles/editRecords.rb +15 -0
  31. data/examples/cookbookfiles/findJohnsLast10Records.rb +17 -0
  32. data/examples/cookbookfiles/findRubyRecords.rb +17 -0
  33. data/examples/cookbookfiles/formatCurrency.rb +24 -0
  34. data/examples/cookbookfiles/formatDate.rb +10 -0
  35. data/examples/cookbookfiles/formatDuration.rb +27 -0
  36. data/examples/cookbookfiles/formatPercent.rb +24 -0
  37. data/examples/cookbookfiles/getAllValuesForFields.rb +18 -0
  38. data/examples/cookbookfiles/getAppDTMInfo.rb +29 -0
  39. data/examples/cookbookfiles/getApplicationVariable.rb +5 -0
  40. data/examples/cookbookfiles/getChildTableDBID.rb +11 -0
  41. data/examples/cookbookfiles/getColumnListForReport.rb +6 -0
  42. data/examples/cookbookfiles/getFieldChoices.rb +13 -0
  43. data/examples/cookbookfiles/getFieldIDs.rb +6 -0
  44. data/examples/cookbookfiles/getFieldNames.rb +6 -0
  45. data/examples/cookbookfiles/getLastModTime.rb +8 -0
  46. data/examples/cookbookfiles/getLastRecModTime.rb +8 -0
  47. data/examples/cookbookfiles/getNumRecords.rb +8 -0
  48. data/examples/cookbookfiles/getNumTables.rb +4 -0
  49. data/examples/cookbookfiles/getRecord.rb +5 -0
  50. data/examples/cookbookfiles/getRecordDisplayURL.rb +13 -0
  51. data/examples/cookbookfiles/getRecordsAddedToday.rb +20 -0
  52. data/examples/cookbookfiles/getRecordsAsJSON.rb +6 -0
  53. data/examples/cookbookfiles/getReportNames.rb +25 -0
  54. data/examples/cookbookfiles/getRoleInfo.rb +48 -0
  55. data/examples/cookbookfiles/getServerStatus.rb +11 -0
  56. data/examples/cookbookfiles/getSortListForReport.rb +6 -0
  57. data/examples/cookbookfiles/getTableIDs.rb +6 -0
  58. data/examples/cookbookfiles/getTableName.rb +8 -0
  59. data/examples/cookbookfiles/getTableNames.rb +25 -0
  60. data/examples/cookbookfiles/getTimeCreated.rb +8 -0
  61. data/examples/cookbookfiles/getTimeInMilliseconds.rb +5 -0
  62. data/examples/cookbookfiles/getUserInfo.rb +26 -0
  63. data/examples/cookbookfiles/getUserRole.rb +15 -0
  64. data/examples/cookbookfiles/intranet.rb +101 -0
  65. data/examples/cookbookfiles/isAverageField.rb +17 -0
  66. data/examples/cookbookfiles/isDbidString.rb +8 -0
  67. data/examples/cookbookfiles/isTotalField.rb +16 -0
  68. data/examples/cookbookfiles/iterateDBPages.rb +8 -0
  69. data/examples/cookbookfiles/iterateFilteredRecords.rb +12 -0
  70. data/examples/cookbookfiles/iterateJoinRecords.rb +68 -0
  71. data/examples/cookbookfiles/iterateRecordInfos.rb +8 -0
  72. data/examples/cookbookfiles/iterateRecords.rb +23 -0
  73. data/examples/cookbookfiles/iterateSummaryRecords.rb +13 -0
  74. data/examples/cookbookfiles/iterateUnionRecords.rb +38 -0
  75. data/examples/cookbookfiles/listAccessibleApplications.rb +6 -0
  76. data/examples/cookbookfiles/logRequestAndResponseXML.rb +8 -0
  77. data/examples/cookbookfiles/lookupFieldPropertyByName.rb +62 -0
  78. data/examples/cookbookfiles/lookupFieldTypeByName.rb +10 -0
  79. data/examples/cookbookfiles/makeCSVFile.rb +4 -0
  80. data/examples/cookbookfiles/makeSlideShow.rb +42 -0
  81. data/examples/cookbookfiles/makerecs.rb +64 -0
  82. data/examples/cookbookfiles/max.rb +26 -0
  83. data/examples/cookbookfiles/min.rb +26 -0
  84. data/examples/cookbookfiles/percent.rb +29 -0
  85. data/examples/cookbookfiles/printChildElements.rb +54 -0
  86. data/examples/cookbookfiles/printNewRecords.rb +12 -0
  87. data/examples/cookbookfiles/processRESTRequest.rb +21 -0
  88. data/examples/cookbookfiles/provisionAndInviteNewUser.rb +13 -0
  89. data/examples/cookbookfiles/purgeRecords.rb +15 -0
  90. data/examples/cookbookfiles/quickbase_adapter.rb.htm +397 -0
  91. data/examples/cookbookfiles/quickbase_record_finder.zip +0 -0
  92. data/examples/cookbookfiles/recordAndFieldIterator.rb +24 -0
  93. data/examples/cookbookfiles/runImport.rb +9 -0
  94. data/examples/cookbookfiles/runQuickBaseTwitterConnector.rb +41 -0
  95. data/examples/cookbookfiles/sendToQuickBase.rb +33 -0
  96. data/examples/cookbookfiles/setDBvar.rb +6 -0
  97. data/examples/cookbookfiles/showRequestAndResponseXML.rb +8 -0
  98. data/examples/cookbookfiles/sqlQuery.rb +11 -0
  99. data/examples/cookbookfiles/stopOnError.rb +10 -0
  100. data/examples/cookbookfiles/sum.rb +26 -0
  101. data/examples/cookbookfiles/twitterFromQuickBase.rb +42 -0
  102. data/examples/cookbookfiles/twitterWithQuickBase.rb +36 -0
  103. data/examples/cookbookfiles/uploadCSVData.rb +20 -0
  104. data/examples/cookbookfiles/uploadExcelData.rb +22 -0
  105. data/examples/cookbookfiles/uploadFileEveryHour.rb +18 -0
  106. data/examples/cookbookfiles/uploadFileIntoNewRecord.rb +8 -0
  107. data/examples/cookbookfiles/uploadFilesFromFolder.exe +0 -0
  108. data/examples/cookbookfiles/uploadFilesFromFolder.rb +69 -0
  109. data/examples/cookbookfiles/useCompanyURL.rb +12 -0
  110. data/examples/cookbookfiles/userRoles.rb +49 -0
  111. data/examples/cookbookfiles/watchCommunityForum.rb +5 -0
  112. data/examples/cookbookfiles/wikifyTable.rb +29 -0
  113. data/examples/cookbookfiles/xmlShortcuts.rb +33 -0
  114. data/examples/pmp/app/controllers/application.rb +7 -0
  115. data/examples/pmp/app/controllers/contacts_controller.rb +8 -0
  116. data/examples/pmp/app/controllers/document_library_controller.rb +2 -0
  117. data/examples/pmp/app/controllers/issues_controller.rb +5 -0
  118. data/examples/pmp/app/controllers/projects_controller.rb +22 -0
  119. data/examples/pmp/app/controllers/resources_controller.rb +2 -0
  120. data/examples/pmp/app/controllers/tasks_controller.rb +13 -0
  121. data/examples/pmp/app/controllers/time_cards_controller.rb +5 -0
  122. data/examples/pmp/app/helpers/application_helper.rb +3 -0
  123. data/examples/pmp/app/helpers/contacts_helper.rb +2 -0
  124. data/examples/pmp/app/helpers/document_library_helper.rb +2 -0
  125. data/examples/pmp/app/helpers/issues_helper.rb +2 -0
  126. data/examples/pmp/app/helpers/projects_helper.rb +2 -0
  127. data/examples/pmp/app/helpers/resources_helper.rb +2 -0
  128. data/examples/pmp/app/helpers/tasks_helper.rb +2 -0
  129. data/examples/pmp/app/helpers/time_cards_helper.rb +2 -0
  130. data/examples/pmp/app/models/contacts.rb +26 -0
  131. data/examples/pmp/app/models/document_library.rb +2 -0
  132. data/examples/pmp/app/models/issues.rb +6 -0
  133. data/examples/pmp/app/models/projects.rb +26 -0
  134. data/examples/pmp/app/models/resources.rb +2 -0
  135. data/examples/pmp/app/models/tasks.rb +12 -0
  136. data/examples/pmp/app/models/time_cards.rb +7 -0
  137. data/examples/pmp/app/schemas/contacts.xml +1 -0
  138. data/examples/pmp/app/schemas/document_library.xml +1 -0
  139. data/examples/pmp/app/schemas/issues.xml +1 -0
  140. data/examples/pmp/app/schemas/pmp.xml +1 -0
  141. data/examples/pmp/app/schemas/projects.xml +1 -0
  142. data/examples/pmp/app/schemas/readme.txt +8 -0
  143. data/examples/pmp/app/schemas/resources.xml +1 -0
  144. data/examples/pmp/app/schemas/tasks.xml +1 -0
  145. data/examples/pmp/app/schemas/time_cards.xml +1 -0
  146. data/examples/pmp/app/views/contacts/companies.rhtml +31 -0
  147. data/examples/pmp/app/views/contacts/project_contacts.rhtml +31 -0
  148. data/examples/pmp/app/views/issues/filter_issues.rhtml +26 -0
  149. data/examples/pmp/app/views/layouts/application.rhtml +56 -0
  150. data/examples/pmp/app/views/projects/all_projects.rhtml +33 -0
  151. data/examples/pmp/app/views/projects/home.rhtml +11 -0
  152. data/examples/pmp/app/views/projects/my_open_projects.rhtml +27 -0
  153. data/examples/pmp/app/views/projects/open_projects.rhtml +44 -0
  154. data/examples/pmp/app/views/projects/project_sorted_by_company.rhtml +40 -0
  155. data/examples/pmp/app/views/projects/projects_sorted_by_priority.rhtml +30 -0
  156. data/examples/pmp/app/views/projects/updated_projects.rhtml +0 -0
  157. data/examples/pmp/app/views/tasks/all_tasks.rhtml +27 -0
  158. data/examples/pmp/app/views/tasks/search.rhtml +23 -0
  159. data/examples/pmp/app/views/tasks/search2.rhtml +23 -0
  160. data/examples/pmp/app/views/tasks/search3.rhtml +23 -0
  161. data/examples/pmp/app/views/time_cards/summary.rhtml +38 -0
  162. data/examples/pmp/config/boot.rb +45 -0
  163. data/examples/pmp/config/database.yml +30 -0
  164. data/examples/pmp/config/environment.rb +60 -0
  165. data/examples/pmp/config/environments/development.rb +21 -0
  166. data/examples/pmp/config/environments/production.rb +18 -0
  167. data/examples/pmp/config/environments/test.rb +19 -0
  168. data/examples/pmp/config/routes.rb +23 -0
  169. data/examples/pmp/db/migrate/001_create_projects.rb +10 -0
  170. data/examples/pmp/db/migrate/002_create_tasks.rb +10 -0
  171. data/examples/pmp/db/migrate/003_create_issues.rb +10 -0
  172. data/examples/pmp/db/migrate/004_create_document_libraries.rb +10 -0
  173. data/examples/pmp/db/migrate/005_create_resources.rb +10 -0
  174. data/examples/pmp/db/migrate/006_create_time_cards.rb +10 -0
  175. data/examples/pmp/db/migrate/007_create_contacts.rb +10 -0
  176. data/examples/pmp/public/404.html +30 -0
  177. data/examples/pmp/public/500.html +30 -0
  178. data/examples/pmp/public/app.index.html +277 -0
  179. data/examples/pmp/public/dispatch.cgi +10 -0
  180. data/examples/pmp/public/dispatch.fcgi +24 -0
  181. data/examples/pmp/public/dispatch.rb +10 -0
  182. data/examples/pmp/public/favicon.ico +0 -0
  183. data/examples/pmp/public/images/rails.png +0 -0
  184. data/examples/pmp/public/javascripts/application.js +2 -0
  185. data/examples/pmp/public/javascripts/controls.js +833 -0
  186. data/examples/pmp/public/javascripts/dragdrop.js +942 -0
  187. data/examples/pmp/public/javascripts/effects.js +1088 -0
  188. data/examples/pmp/public/javascripts/prototype.js +2515 -0
  189. data/examples/pmp/public/robots.txt +1 -0
  190. data/examples/pmp/test/fixtures/contacts.yml +5 -0
  191. data/examples/pmp/test/fixtures/document_libraries.yml +5 -0
  192. data/examples/pmp/test/fixtures/issues.yml +5 -0
  193. data/examples/pmp/test/fixtures/projects.yml +5 -0
  194. data/examples/pmp/test/fixtures/resources.yml +5 -0
  195. data/examples/pmp/test/fixtures/tasks.yml +5 -0
  196. data/examples/pmp/test/fixtures/time_cards.yml +5 -0
  197. data/examples/pmp/test/functional/contacts_controller_test.rb +18 -0
  198. data/examples/pmp/test/functional/document_library_controller_test.rb +18 -0
  199. data/examples/pmp/test/functional/issues_controller_test.rb +18 -0
  200. data/examples/pmp/test/functional/projects_controller_test.rb +18 -0
  201. data/examples/pmp/test/functional/resources_controller_test.rb +18 -0
  202. data/examples/pmp/test/functional/tasks_controller_test.rb +18 -0
  203. data/examples/pmp/test/functional/time_cards_controller_test.rb +18 -0
  204. data/examples/pmp/test/test_helper.rb +28 -0
  205. data/examples/pmp/test/unit/contacts_test.rb +10 -0
  206. data/examples/pmp/test/unit/document_library_test.rb +10 -0
  207. data/examples/pmp/test/unit/issues_test.rb +10 -0
  208. data/examples/pmp/test/unit/projects_test.rb +10 -0
  209. data/examples/pmp/test/unit/resources_test.rb +10 -0
  210. data/examples/pmp/test/unit/tasks_test.rb +10 -0
  211. data/examples/pmp/test/unit/time_cards_test.rb +10 -0
  212. data/lib/QuickBaseClient.rb +5054 -0
  213. data/lib/QuickBaseCommandLineClient.rb +401 -0
  214. data/lib/QuickBaseContactsAppBuilder.rb +419 -0
  215. data/lib/QuickBaseEmailer.rb +334 -0
  216. data/lib/QuickBaseEventNotifier.rb +592 -0
  217. data/lib/QuickBaseMisc.rb +96 -0
  218. data/lib/QuickBaseObjects.rb +566 -0
  219. data/lib/QuickBaseRSSGenerator.rb +286 -0
  220. data/lib/QuickBaseTextData.rb +545 -0
  221. data/lib/QuickBaseTwitterConnector.rb +300 -0
  222. data/lib/QuickBaseWebClient.rb +126 -0
  223. data/lib/WorkPlaceClient.rb +45 -0
  224. data/lib/qbc.makeCSVFile.qbc +4 -0
  225. data/lib/qbc.makeCSVFile.rb +17 -0
  226. data/lib/quickbase_adapter.rb +320 -0
  227. data/lib/runFieldEntryDialog.rb +151 -0
  228. data/lib/runOfflineFieldEntryDialog.rb +203 -0
  229. data/rakefile +100 -0
  230. data/test/run_tests.bat +7 -0
  231. data/test/spec_all_tests.rb +13 -0
  232. data/test/spec_smoke_tests.rb +58 -0
  233. data/test/spec_workplace_addrecord_test.rb +46 -0
  234. data/test/spec_workplace_base_test.rb +57 -0
  235. data/test/spec_workplace_editrecord_test.rb +38 -0
  236. data/test/spec_workplace_json_test.rb +38 -0
  237. data/test/spec_workplace_objects_test.rb +39 -0
  238. data/test/spec_workplace_smoke_tests.rb +45 -0
  239. metadata +353 -0
@@ -0,0 +1,96 @@
1
+ #--#####################################################################
2
+ # Copyright (c) 2009 Gareth Lewis and Intuit, Inc.
3
+ #
4
+ # All rights reserved. This program and the accompanying materials
5
+ # are made available under the terms of the Eclipse Public License v1.0
6
+ # which accompanies this distribution, and is available at
7
+ # http://www.opensource.org/licenses/eclipse-1.0.php
8
+ #
9
+ # Contributors:
10
+ # Gareth Lewis - Initial contribution.
11
+ # Intuit Partner Platform.
12
+ #++#####################################################################
13
+
14
+ module QuickBase
15
+
16
+ # Miscellaneous static helper methods
17
+ class Misc
18
+
19
+ def Misc.ruby19?
20
+ RUBY_VERSION >= "1.9"
21
+ end
22
+
23
+ def Misc.createBase32ConversionHash
24
+ base32Symbols = {}
25
+ decimal = 0
26
+ ("a".."z").each{|letter|
27
+ unless letter == "l" or letter == "o"
28
+ base32Symbols[decimal.to_s]=letter
29
+ decimal += 1
30
+ end
31
+ }
32
+ (2..9).each{|number|
33
+ base32Symbols[decimal.to_s]=number.to_s
34
+ decimal += 1
35
+ }
36
+ base32Symbols
37
+ end
38
+
39
+ def Misc.decimalToBase32(decimalNumber)
40
+ @base32Symbols ||= Misc.createBase32ConversionHash
41
+ base32Num = ""
42
+ decimalNumber = decimalNumber.to_i
43
+ if decimalNumber < 32
44
+ base32Num = @base32Symbols[decimalNumber.to_s]
45
+ else
46
+ power = 10
47
+ power -= 1 while (decimalNumber/(32**power)) < 1
48
+ while decimalNumber > 0
49
+ n = (decimalNumber/(32**power))
50
+ base32Num << @base32Symbols[n.to_s] if @base32Symbols[n.to_s]
51
+ decimalNumber = (decimalNumber-((32**power)*n))
52
+ power -= 1
53
+ end
54
+ end
55
+ base32Num
56
+ end
57
+
58
+ def Misc.isBase32Number?(string)
59
+ ret = true
60
+ if string
61
+ @base32Symbols ||= Misc.createBase32ConversionHash
62
+ base32SymbolsValues = @base32Symbols.values
63
+ stringCopy = string.to_s
64
+ stringCopy.split(//).each{|char|
65
+ if !base32SymbolsValues.include?(char)
66
+ ret = false
67
+ break
68
+ end
69
+ }
70
+ else
71
+ ret = false
72
+ end
73
+ ret
74
+ end
75
+
76
+ def Misc.isDbidString?(string)
77
+ Misc.isBase32Number?(string)
78
+ end
79
+
80
+ def Misc.time_in_milliseconds(time = nil)
81
+ ret = 0
82
+ time ||= Time.now
83
+ if time.is_a?(Time)
84
+ ret = (time.to_f * 1000).to_i
85
+ elsif time.is_a?(DateTime)
86
+ t = Time.mktime(time.year,time.month,time.day,time.hour,time.min,time.sec,0)
87
+ ret = (t.to_f * 1000).to_i
88
+ elsif time.is_a?(Date)
89
+ t = Time.mktime(time.year,time.month,time.day,0,0,0,0)
90
+ ret = (t.to_f * 1000).to_i
91
+ end
92
+ ret
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,566 @@
1
+ #--#####################################################################
2
+ # Copyright (c) 2009 Gareth Lewis and Intuit, Inc.
3
+ #
4
+ # All rights reserved. This program and the accompanying materials
5
+ # are made available under the terms of the Eclipse Public License v1.0
6
+ # which accompanies this distribution, and is available at
7
+ # http://www.opensource.org/licenses/eclipse-1.0.php
8
+ #
9
+ # Contributors:
10
+ # Gareth Lewis - Initial contribution.
11
+ # Intuit Partner Platform.
12
+ #++#####################################################################
13
+
14
+ require 'QuickBaseClient'
15
+
16
+ module QuickBase
17
+
18
+ module Objects
19
+
20
+ # Generic list of attributes (used in Field class).
21
+ class Attributes < Hash; end
22
+
23
+ # Generic list of properties (used in Field and Query classes).
24
+ class Properties < Hash; end
25
+
26
+ # List of Field definitions (used in Table class).
27
+ class Fields < Hash; end
28
+
29
+ # List of Choices for a multi-choice text field definition (used in Field class).
30
+ class FieldChoices < Array; end
31
+
32
+ # List of Application variables.
33
+ class Variables < Hash; end
34
+
35
+ # General info for Table and Application classes.
36
+ class Info < Hash; end
37
+
38
+ # List of Queries (used in Table class).
39
+ class Queries < Hash; end
40
+
41
+ # List of Tables - child tables of Application table.
42
+ class Tables < Hash; end
43
+
44
+ # List of pages in an Application .
45
+ class Pages < Hash; end
46
+
47
+ # List of Roles in an application.
48
+ class Roles < Hash; end
49
+
50
+ # List of Users in an Application.
51
+ class Users < Hash; end
52
+
53
+ # List of field values from a Record.
54
+ class FieldValues < Hash; end
55
+
56
+ # List of records returned by a Query.
57
+ class Records < Array; end
58
+
59
+ # Definition of a Field built from the XML schema for a Table.
60
+ class Field
61
+ attr_reader :name, :attributes, :properties
62
+ attr_accessor :qbc
63
+ def initialize(name = nil,type = nil,qbc = nil)
64
+ set_qbc(qbc) if qbc
65
+ @name = name || "new_field"
66
+ @name = @name.strip.gsub(" ","_")
67
+ @type = type || "text"
68
+ end
69
+ def set_qbc(qbc)
70
+ @qbc = qbc
71
+ @dbid = qbc.dbid.dup
72
+ end
73
+ def build(field_xml,qbc)
74
+ @qbc = qbc
75
+ @dbid = qbc.dbid.dup
76
+ @id = field_xml.attributes["id"]
77
+ @attributes = Attributes.new
78
+ field_xml.attributes.each_attribute{|attribute|
79
+ @attributes[attribute.expanded_name]=attribute.value
80
+ }
81
+ @properties = Properties.new
82
+ @choices = FieldChoices.new
83
+ fieldProc = proc { |element|
84
+ if element.is_a?(REXML::Element)
85
+ if element.name == "choice"
86
+ @choices << element.text
87
+ else
88
+ @properties[element.name] = element.has_text? ? element.text : nil
89
+ end
90
+ end
91
+ }
92
+ @qbc.processChildElements(field_xml,true,fieldProc)
93
+ @name = @properties["label"].strip.gsub(" ","_")
94
+ @attributes.each{|key,value|
95
+ self.class.send(:define_method,key){@attributes[key]}
96
+ }
97
+ @properties.each{|key,value|
98
+ self.class.send(:define_method,key){@properties[key]}
99
+ }
100
+ end
101
+ def addChoice(choice, qbc = nil)
102
+ set_qbc(qbc) if qbc
103
+ @qbc.fieldAddChoices( @dbid, @id, choice )
104
+ end
105
+ def removeChoice(choice, qbc = nil)
106
+ set_qbc(qbc) if qbc
107
+ @qbc.fieldRemoveChoices(@dbid, fid, choice)
108
+ end
109
+ def setProperties(new_properties)
110
+ @properties.merge!(new_properties) if @qbc.setFieldProperties( @dbid, new_properties, @id )
111
+ end
112
+ end
113
+
114
+ # Definition of a Query built from the XML schema for a Table.
115
+ class Query
116
+ attr_reader :id, :name, :properties
117
+ def build(query_xml,qbc)
118
+ @qbc = qbc
119
+ @dbid = qbc.dbid.dup
120
+ @id = query_xml.attributes["id"]
121
+ @properties = Properties.new
122
+ queryProc = proc { |element|
123
+ if element.is_a?(REXML::Element)
124
+ @properties[element.name] = element.has_text? ? element.text : nil
125
+ end
126
+ }
127
+ @qbc.processChildElements(query_xml,true,queryProc)
128
+ @properties.each{|key,value|
129
+ self.class.send(:define_method,key){@properties[key]}
130
+ }
131
+ @name = @properties["qyname"]
132
+ end
133
+ # Run the Query and get the Records returned.
134
+ def run
135
+ ridFieldName = @qbc.lookupFieldNameFromID( "3")
136
+ records = Records.new
137
+ @qbc.iterateRecords(@dbid,@qbc.getFieldNames(@dbid),nil,@id,nil,qyclst()){|qb_record|
138
+ record = Record.new
139
+ record.build(@qbc,ridFieldName, qb_record)
140
+ records << record
141
+ }
142
+ records
143
+ end
144
+ end
145
+
146
+ # Name and value of an Application variable.
147
+ class Variable
148
+ attr_reader :name, :value
149
+ def initialize(key=nil,value=nil)
150
+ build(key,value) if key and value
151
+ end
152
+ def build(key,value)
153
+ @name = key
154
+ @value = value
155
+ end
156
+ end
157
+
158
+ # Definition of a Table built from the XML schema for the table.
159
+ class Table
160
+ attr_reader :dbid, :name, :desc, :info, :tables, :queries, :fields, :pnoun
161
+ def initialize(pnoun=nil)
162
+ @pnoun = pnoun || "Records"
163
+ end
164
+ def build(qbc,appTable=false)
165
+ @qbc = qbc
166
+ @dbid = qbc.dbid.dup
167
+ @name = qbc.dbname.dup if qbc.dbname
168
+ buildInfo
169
+ buildFields
170
+ buildQueries
171
+ if appTable
172
+ buildAppInfo
173
+ buildVariables
174
+ buildPages
175
+ buildRoles
176
+ buildUsers
177
+ buildTables
178
+ end
179
+ self
180
+ end
181
+ def buildInfo
182
+ buildInfoField("lastRecModTime",@qbc.lastRecModTime)
183
+ buildInfoField("lastModifiedTime",@qbc.lastModifiedTime)
184
+ buildInfoField("createdTime",@qbc.createdTime)
185
+ buildInfoField("lastAccessTime",@qbc.lastAccessTime)
186
+ buildInfoField("numRecords",@qbc.numRecords)
187
+ buildInfoField("mgrID",@qbc.mgrID)
188
+ buildInfoField("mgrName",@qbc.mgrName)
189
+ buildInfoField("dbname",@qbc.dbname)
190
+ buildInfoField("version",@qbc.version)
191
+ end
192
+ def buildAppInfo
193
+ buildInfoField("requestTime",@qbc.requestTime)
194
+ buildInfoField("requestNextAllowedTime",@qbc.requestNextAllowedTime)
195
+ end
196
+ def buildInfoField(key,value)
197
+ @info ||= Info.new
198
+ @info[key] = value
199
+ self.class.send(:define_method,"i#{key}") {@info[key]}
200
+ end
201
+ def buildFields
202
+ @fields ||= Fields.new
203
+ fieldsProc = proc { |element|
204
+ if element.is_a?(REXML::Element) and element.name == "field"
205
+ buildField(element)
206
+ end
207
+ }
208
+ @qbc.processChildElements(@qbc.fields,false,fieldsProc)
209
+ end
210
+ def buildField(field_xml)
211
+ field = Field.new
212
+ field.build(field_xml,@qbc)
213
+ @fields[field.id] = field
214
+ addFieldMethods(field)
215
+ end
216
+ def addFieldMethods(field)
217
+ self.class.send(:define_method,"f#{field.name}") {@fields[field.id]}
218
+ end
219
+ def addField(field)
220
+ raise "#{field} is not a Field object." if ! field.is_a?(Field)
221
+ field.id = @qbc.addField(@dbid,field.name,field.type)
222
+ @fields[field.id] = field
223
+ addFieldMethods(field)
224
+ end
225
+ def deleteField(field)
226
+ raise "#{field} is not a Field object." if ! field.is_a?(Field)
227
+ removeFieldMethods(field)
228
+ @fields.delete(field.id)
229
+ @qbc.deleteField(@dbid,field.id)
230
+ end
231
+ def removeFieldMethods(field)
232
+ raise "#{field} is not a Field object." if ! field.is_a?(Field)
233
+ self.class.send(:remove_method,"f#{field.name}")
234
+ end
235
+ def buildVariables
236
+ @variables ||= Variables.new
237
+ @qbc.getApplicationVariables.each{|key,value| buildVariable(key,value)}
238
+ end
239
+ def buildVariable(key,value)
240
+ variable = Variable.new
241
+ variable.build(key,value)
242
+ @variables[key] = variable
243
+ addVariableMethods(variable)
244
+ end
245
+ def addVariableMethods(variable)
246
+ self.class.send(:define_method,"v#{variable.name}") {@variables[variable.name].value}
247
+ self.class.send(:define_method,"v#{variable.name}=") {|valueToAssign|
248
+ @variables[variable.name].value = valueToAssign
249
+ @qbc.setDBVar(@dbid,variable.name,valueToAssign)
250
+ }
251
+ end
252
+ def buildTables
253
+ @tables ||= Tables.new
254
+ @qbc.getTableIDs(@dbid).each { |chdbid| buildTable(chdbid) }
255
+ end
256
+ def buildTable(dbid)
257
+ table = Table.new
258
+ @qbc.getDBInfo(dbid)
259
+ @qbc.getSchema(dbid)
260
+ table.build(@qbc)
261
+ @tables[dbid] = table
262
+ addTableMethods(table)
263
+ end
264
+ def addTableMethods(table)
265
+ self.class.send(:define_method,"t#{table.name.strip.gsub(' ','_')}"){@tables[table.dbid]}
266
+ end
267
+ def buildQueries
268
+ @queries ||= Queries.new
269
+ queriesProc = proc { |element|
270
+ if element.is_a?(REXML::Element) and element.name == "query"
271
+ buildQuery(element)
272
+ end
273
+ }
274
+ @qbc.processChildElements(@qbc.queries,false,queriesProc)
275
+ end
276
+ def buildQuery(query_xml)
277
+ query = Query.new
278
+ query.build(query_xml,@qbc)
279
+ @queries[query.id] = query
280
+ self.class.send(:define_method,"q#{query.name.strip.gsub(' ','_')}"){@queries[query.id]}
281
+ end
282
+ def buildPages
283
+ @pages ||= Pages.new
284
+ pageList = @qbc.getDBPagesAsArray(@dbid)
285
+ pageList.each{|pageHash|buildPage(pageHash)}
286
+ end
287
+ def buildPage(pageHash)
288
+ page = Page.new
289
+ page.build(pageHash)
290
+ @pages[page.id]=page
291
+ addPageMethods(page)
292
+ end
293
+ def addPageMethods(page)
294
+ self.class.send(:define_method,"p#{page.name.strip.gsub(' ','_')}"){@pages[page.id]}
295
+ self.class.send(:define_method,"p#{page.name.strip.gsub(' ','_')}="){|pagebody|
296
+ @pages[page.id].content = pagebody.dup
297
+ @qbc.addReplaceDBPage(@dbid, page.id, nil, nil, pagebody)
298
+ }
299
+ end
300
+ def buildRoles
301
+ @roles ||= Roles.new
302
+ @qbc.getRoleInfo( @dbid ) {|role|buildRole(role)}
303
+ end
304
+ def buildRole(role_xml)
305
+ role = Role.new
306
+ role.build(role_xml,@qbc)
307
+ @roles[role.id] = role
308
+ self.class.send(:define_method,"r#{role.name.strip.gsub(' ','_')}"){@roles[role.id]}
309
+ end
310
+ def buildUsers
311
+ @users ||= Users.new
312
+ @qbc.userRoles(@dbid){|user_role_xml|buildUser(user_role_xml)}
313
+ end
314
+ def buildUser(user_role_xml)
315
+ user = User.new
316
+ user.build(user_role_xml,@qbc)
317
+ @users[user.id] = user
318
+ addUserMethods(user)
319
+ end
320
+ def addUserMethods(user)
321
+ self.class.send(:define_method,"u#{user.name.strip.gsub(' ','_')}"){@users[user.id]}
322
+ end
323
+ def runImport(importid)
324
+ @qbc.runImport(@dbid,importid)
325
+ end
326
+ end
327
+
328
+ # Definition and content of a page associated with an Application.
329
+ class Page
330
+ attr_reader :id, :name, :type, :content
331
+ def initialize(pageHash=nil)
332
+ build(pageHash) if pageHash
333
+ end
334
+ def build(pageHash)
335
+ raise "#{pageHash} is not a Hash." if !pageHash.is_a?(Hash)
336
+ @id = pageHash["id"] if pageHash["id"]
337
+ @name = pageHash["name"] if pageHash["name"]
338
+ @name ||= "Unnamed page"
339
+ @type = pageHash["type"] if pageHash["type"]
340
+ @type ||= "1"
341
+ @content = pageHash["content"] if pageHash["content"]
342
+ end
343
+ end
344
+
345
+ # A Role associated with an Application.
346
+ class Role
347
+ attr_reader :id, :name, :access_id, :access
348
+ def build(role_xml,qbc)
349
+ raise "role_xml is not an XML element" if !role_xml.is_a?(REXML::Element)
350
+ @qbc = qbc
351
+ @dbid = qbc.dbid.dup
352
+ @id = role_xml.attributes["id"]
353
+ @name = role_xml.elements["name"].text.dup
354
+ @access = role_xml.elements["access"].text.dup
355
+ @access_id = role_xml.elements["access"].attributes["id"]
356
+ end
357
+ def addUser(user)
358
+ raise "#{user} is not a User object" if !is_a?(User)
359
+ @qbc.addUserToRole(@dbid,user.id,id)
360
+ end
361
+ def removeUser(user)
362
+ raise "#{user} is not a User object" if !is_a?(User)
363
+ @qbc.removeUserFromRole(@dbid,user.id,role.id)
364
+ end
365
+ end
366
+
367
+ # A User with access to an Application.
368
+ class User
369
+ attr_reader :id, :login, :screenName, :email, :name, :firstname, :lastname, :roles, :externalAuth
370
+ def set_qbc(qbc)
371
+ @qbc = qbc
372
+ @dbid = qbc.dbid.dup
373
+ end
374
+ def build(user_role_xml,qbc)
375
+ raise "user_role_xml is not an XML element" if !user_role_xml.is_a?(REXML::Element)
376
+ set_qbc(qbc)
377
+ @id = user_role_xml.attributes["id"]
378
+ @name = user_role_xml.elements["name"].text.dup
379
+ @roles = []
380
+ rolesProc = proc { |element|
381
+ if element.is_a?(REXML::Element) and element.name == "role"
382
+ roles << element.attributes["id"]
383
+ end
384
+ }
385
+ qbc.processChildElements(user_role_xml,false,rolesProc)
386
+ end
387
+ def addInfo(qbc,email)
388
+ set_qbc(qbc)
389
+ @qbc.getUserInfo(email)
390
+ @name = @qbc.name
391
+ @firstName = @qbc.firstName
392
+ @lastName = @qbc.lastName
393
+ @login = @qbc.login
394
+ @email = @qbc.email
395
+ @screenName = @qbc.screenName
396
+ @externalAuth = @qbc.externalAuth
397
+ @id = @qbc.userid
398
+ @qbc.getUserRole(@dbid, @id)
399
+ @roles ||= []
400
+ @roles << @qbc.roleid.dup
401
+ end
402
+ def changeRole(role,new_role)
403
+ raise "#{role} is not a Role object" if !is_a?(Role)
404
+ raise "#{new_role} is not a Role object" if !is_a?(Role)
405
+ @qbc.addUserToRole(@dbid,id,role.id,new_role.id)
406
+ end
407
+ end
408
+
409
+ # An Application, which is a Table with child Tables, Pages, Roles, Variables.
410
+ class Application < Table
411
+ attr_reader :pages, :roles, :users, :variables
412
+ def addTable(table)
413
+ raise "#{table} is not a Table object" if !is_a?(Table)
414
+ newdbid = @qbc.createTable(@dbid, table.pnoun)
415
+ @tables[newdbid] = table
416
+ addTableMethods(table)
417
+ end
418
+ def addVariable(variable)
419
+ raise "#{variable} is not a Variable object" if !is_a?(Variable)
420
+ @variables[variable.name] = variable
421
+ addVariableMethods(variable)
422
+ end
423
+ def addPage(page)
424
+ raise "#{page} is not a Page object" if !is_a?(Page)
425
+ pageid = @qbc.addReplaceDBPage(@dbid,nil,page.name, page.type, page.content)
426
+ page.build( {"id" => pageid})
427
+ @pages[pageid] = page
428
+ addPageMethods(page)
429
+ end
430
+ def addUser(role,email,fname,lname,message)
431
+ raise "#{role} is not a Role object" if !is_a?(Role)
432
+ userid = @qbc.provisionUser(@dbid, role.id, email, fname, lname)
433
+ if userid
434
+ if @qbc.sendInvitation(@dbid, userid, message)
435
+ user = User.new
436
+ user.addInfo(qbc,email)
437
+ end
438
+ end
439
+ end
440
+ def rename(newappname)
441
+ @qbc.renameApp(@dbid, newappname)
442
+ end
443
+ end
444
+
445
+ # Name and value of a field in a Record return by a Query.
446
+ class FieldValue
447
+ attr_reader :name, :value
448
+ def initialize(k,v)
449
+ @name = k.dup
450
+ @value = v.dup
451
+ end
452
+ end
453
+
454
+ # A Record returned by a Query.
455
+ class Record
456
+ attr_reader :id, :fieldValues
457
+ def build(qbc, ridFieldName,qb_record)
458
+ @qbc = qbc
459
+ @dbid = qbc.dbid.dup
460
+ @fieldValues = FieldValues.new
461
+ qb_record.each{|k,v|
462
+ @id = v if k == ridFieldName
463
+ fieldValue = FieldValue.new(k,v)
464
+ @fieldValues[fieldValue.name] = fieldValue.value
465
+ addMethods(fieldValue)
466
+ }
467
+ end
468
+ def addMethods(fieldValue)
469
+ self.class.send(:define_method,"f#{fieldValue.name.strip.gsub(' ','_')}"){@fieldValues[fieldValue.name]}
470
+ self.class.send(:define_method,"f#{fieldValue.name.strip.gsub(' ','_')}="){|valueToAssign|
471
+ @fieldValues[fieldValue.name] = valueToAssign
472
+ @qbc.setFieldValue(fieldValue.name,valueToAssign,@dbid,@id)
473
+ }
474
+ end
475
+ end
476
+
477
+ # Build objects using XML from QuickBase
478
+ class Builder
479
+ def initialize(username=nil,password=nil,qbc=nil)
480
+ @qbc = qbc || Client.new(username,password)
481
+ @qbc.cacheSchemas=true
482
+ end
483
+ def application(application_name)
484
+ dbid = @qbc.findDBByName(application_name)
485
+ if dbid
486
+ @qbc._getAppDTMInfo
487
+ @qbc._getDBInfo
488
+ @qbc._getSchema
489
+ a = Application.new
490
+ a.build(@qbc,true)
491
+ else
492
+ raise "Could not find the application named '#{application_name}'."
493
+ end
494
+ end
495
+ def table(dbid)
496
+ begin
497
+ @qbc.getDBInfo(dbid)
498
+ @qbc.getSchema(dbid)
499
+ t = Table.new
500
+ t.build(@qbc)
501
+ rescue
502
+ raise "Could not find the table using '#{dbid}' as a dbid."
503
+ end
504
+ end
505
+ end
506
+
507
+ end # module Objects
508
+
509
+ end # module QuickBase
510
+
511
+ def applicationObjectExample
512
+
513
+ qbob = QuickBase::Objects::Builder.new(ENV["quickbase_username"],ENV["quickbase_password"])
514
+
515
+ cookbookApp = qbob.application("QuickBase API Cookbook v3")
516
+
517
+ puts "\n\nApplication name:\n"
518
+ puts cookbookApp.name
519
+
520
+ puts "\n\nApplication roles:\n"
521
+ cookbookApp.roles.each_value{|role|puts "name: #{role.name}, id: #{role.id}, access: #{role.access}"}
522
+
523
+ puts "\n\nApplication users:\n"
524
+ cookbookApp.users.each_value{|user|puts "id: #{user.id}"}
525
+
526
+ puts "\n\nApplication variables:\n"
527
+ cookbookApp.variables.each_value{|variable|puts "#{variable.name}: #{variable.value}"}
528
+
529
+ puts "\n\nValue of application variable 'TestVariable':\n"
530
+ puts cookbookApp.vTestVariable
531
+
532
+ puts "\n\nApplication pages:\n"
533
+ cookbookApp.pages.each_value{|page|puts page.name}
534
+
535
+ puts "\n\nDefault application page:\n"
536
+ puts cookbookApp.pDefault_Dashboard.name
537
+
538
+ puts "\n\nTables from the QuickBase API Cookbook v3:\n"
539
+ cookbookApp.tables.each_value{|table|puts table.name}
540
+
541
+ puts "\n\nQueries from the Recipes table:\n"
542
+ cookbookApp.tRecipes.queries.each_value{|query|puts query.name}
543
+
544
+ puts "\n\nProperties of the List All query from the Recipes table:\n"
545
+ cookbookApp.tRecipes.qList_All.properties.each_pair{|key,value|puts "#{key}: #{value}" }
546
+
547
+ puts "\n\nRecord Titles from the List All query from the Recipes table:\n"
548
+ records = cookbookApp.tRecipes.qList_All.run
549
+ records.each{|record| puts record.fTitle}
550
+
551
+ puts "\n\nColumns of the List All query from the Recipes table:\n"
552
+ puts cookbookApp.tRecipes.qList_All.qyclst
553
+
554
+ puts "\n\nFields from the Ingredients table:\n"
555
+ cookbookApp.tIngredients.fields.each_value{|field|puts field.name}
556
+
557
+ puts "\n\nField ID of the Description field in the Ingredients table:\n"
558
+ puts cookbookApp.tIngredients.fDescription.id
559
+
560
+ puts "\n\nName of field 7 from the Ingredients table:\n"
561
+ puts cookbookApp.tIngredients.fields["7"].name
562
+
563
+
564
+ end
565
+
566
+ #applicationObjectExample