lib/QuickBaseClient.rb in quickbase_client-1.0.2 vs lib/QuickBaseClient.rb in quickbase_client-1.0.3
- old
+ new
@@ -11,14 +11,20 @@
# Intuit Partner Platform.
#++#####################################################################
require 'rexml/document'
require 'net/https'
-require 'socket'
require 'json'
require 'QuickBaseMisc'
+begin
+ require 'httpclient'
+ USING_HTTPCLIENT = true
+rescue LoadError
+ USING_HTTPCLIENT = false
+end
+
module QuickBase
# QuickBase client: Version 1.0.0: Ruby wrapper class for QuickBase HTTP API.
# The class's method and member variable names correspond closely to the QuickBase HTTP API reference.
# This class was written using ruby 1.8.6.
@@ -142,29 +148,40 @@
options["proxy_options"])
end
# Initializes the connection to QuickBase.
def setHTTPConnection( useSSL, org = "www", domain = "quickbase", proxy_options = nil )
+ @useSSL = useSSL
@org = org
@domain = domain
- if proxy_options
- @httpProxy = Net::HTTP::Proxy(proxy_options["proxy_server"], proxy_options["proxy_port"], proxy_options["proxy_user"], proxy_options["proxy_password"])
- @httpConnection = @httpProxy.new( "#{@org}.#{@domain}.com", useSSL ? 443 : 80)
- else
- @httpConnection = Net::HTTP.new( "#{@org}.#{@domain}.com", useSSL ? 443 : 80 )
- end
- @httpConnection.use_ssl = useSSL
- @httpConnection.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ if USING_HTTPCLIENT
+ if proxy_options
+ @httpConnection = HTTPClient.new( "#{proxy_options["proxy_server"]}:#{proxy_options["proxy_port"] || useSSL ? "443" : "80"}" )
+ @httpConnection.set_auth(proxy_options["proxy_server"], proxy_options["proxy_user"], proxy_options["proxy_password"])
+ else
+ @httpConnection = HTTPClient.new
+ end
+ else
+ if proxy_options
+ @httpProxy = Net::HTTP::Proxy(proxy_options["proxy_server"], proxy_options["proxy_port"], proxy_options["proxy_user"], proxy_options["proxy_password"])
+ @httpConnection = @httpProxy.new( "#{@org}.#{@domain}.com", useSSL ? 443 : 80)
+ else
+ @httpConnection = Net::HTTP.new( "#{@org}.#{@domain}.com", useSSL ? 443 : 80 )
+ end
+ @httpConnection.use_ssl = useSSL
+ @httpConnection.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ end
end
# Causes useful information to be printed to the screen for every HTTP request.
def debugHTTPConnection()
- @httpConnection.set_debug_output $stdout if @httpConnection
+ @httpConnection.set_debug_output $stdout if @httpConnection and USING_HTTPCLIENT == false
end
# Sets the QuickBase URL and port to use for requests.
def setqbhost( useSSL, org = "www", domain = "quickbase" )
+ @useSSL = useSSL
@org = org
@domain = domain
@qbhost = useSSL ? "https://#{@org}.#{@domain}.com:443" : "http://#{@org}.#{@domain}.com"
@qbhost
end
@@ -214,12 +231,18 @@
@logger.logRequest( @dbidForRequestURL, api_Request, @requestXML ) if @logger
begin
# send the request
- @responseCode, @responseXML = @httpConnection.post( @requestURL, @requestXML, @requestHeaders )
-
+ if USING_HTTPCLIENT
+ response = @httpConnection.post( @requestURL, @requestXML, @requestHeaders )
+ @responseCode = response.status
+ @responseXML = response.content
+ else
+ @responseCode, @responseXML = @httpConnection.post( @requestURL, @requestXML, @requestHeaders )
+ end
+
printResponse( @responseCode, @responseXML ) if @printRequestsAndResponses
if not isHTMLRequest
processResponse( @responseXML )
end
@@ -350,11 +373,11 @@
def processResponse( responseXML )
fire( "onProcessResponse" )
parseResponseXML( responseXML )
- @ticket = getResponseValue( :ticket ) if @ticket.nil?
+ @ticket ||= getResponseValue( :ticket )
@udata = getResponseValue( :udata )
getErrorInfoFromResponse
end
# Extracts error info from XML responses returned by QuickBase.
@@ -386,10 +409,11 @@
end
# Gets the value for a specific field at the top level
# of the XML returned from QuickBase.
def getResponseValue( field )
+ @fieldValue = nil
if field and @responseXMLdoc
@fieldValue = @responseXMLdoc.root.elements[ field.to_s ]
@fieldValue = fieldValue.text if fieldValue and fieldValue.has_text?
end
@fieldValue
@@ -488,17 +512,18 @@
findElementsByAttributeValue( @fields, "field_type", type )
end
# Returns the value of a field property, or nil.
def lookupFieldPropertyByName( fieldName, property )
+ theproperty = nil
if isValidFieldProperty?(property)
fid = lookupFieldIDByName( fieldName )
field = lookupField( fid ) if fid
- theproperty = nil
theproperty = field.elements[ property ] if field
theproperty = theproperty.text if theproperty and theproperty.has_text?
end
+ theproperty
end
# Returns whether a field will show a Total on reports.
def isTotalField?(fieldName)
does_total = lookupFieldPropertyByName(fieldName,"does_total")
@@ -689,11 +714,11 @@
element
end
# Returns an array of XML sub-elements with the specified attribute value.
def findElementsByAttributeValue( elements, attribute_name, attribute_value )
- elementArray = Array.new
+ elementArray = []
if elements
if elements.is_a?( REXML::Element )
elements.each_element_with_attribute( attribute_name, attribute_value ) { |e| elementArray << e }
elsif elements.is_a?( Array )
elements.each{ |e|
@@ -706,11 +731,11 @@
elementArray
end
# Returns an array of XML sub-elements with the specified attribute name.
def findElementsByAttributeName( elements, attribute_name )
- elementArray = Array.new
+ elementArray = []
if elements
elements.each_element_with_attribute( attribute_name ) { |e| elementArray << e }
end
elementArray
end
@@ -953,11 +978,11 @@
numTables = 0
dbid ||= @dbid
if getSchema(dbid)
if @chdbids
chdbidArray = findElementsByAttributeName( @chdbids, "name" )
- chdbidArray.each{|chdbid| numTables += 1 }
+ numTables = chdbidArray.length
end
end
numTables
end
@@ -988,15 +1013,13 @@
ret
end
# Returns whether a given string represents a valid QuickBase field type.
def isValidFieldType?( type )
- if @validFieldTypes.nil?
- @validFieldTypes = %w{ checkbox dblink date duration email file fkey float formula currency
+ @validFieldTypes ||= %w{ checkbox dblink date duration email file fkey float formula currency
lookup phone percent rating recordid text timeofday timestamp url userid icalendarbutton }
- end
- ret = @validFieldTypes.include?( type )
+ @validFieldTypes.include?( type )
end
# Returns a field type string given the more human-friendly label for a field type.
def fieldTypeForLabel( fieldTypeLabel )
@fieldTypeLabelMap ||= Hash["Text","text","Numeric","float","Date / Time","timestamp","Date","date","Checkbox","checkbox","Database Link","dblink","Duration","duration","Email","email","File Attachment","file","Numeric-Currency","currency","Numeric-Rating","rating","Numeric-Percent","percent","Phone Number","phone","Relationship","fkey","Time Of Day","timeofday","URL","url","User","user","Record ID#","recordid","Report Link","dblink","iCalendar","icalendarbutton"]
@@ -1107,11 +1130,11 @@
# * name: label of the field value to be set.
# * fid: id of the field to be set.
# * filename: if the field is a file attachment field, the name of the file that should be displayed in QuickBase.
# * value: the value to set in this field. If the field is a file attachment field, the name of the file that should be uploaded into QuickBase.
def addFieldValuePair( name, fid, filename, value )
- @fvlist = Array.new if @fvlist.nil?
+ @fvlist ||= []
@fvlist << FieldValuePairXML.new( self, name, fid, filename, value ).to_s
@fvlist
end
# Replaces a field value in the list of fields to be set by the next addRecord() or editRecord() call to QuickBase.
@@ -1145,11 +1168,11 @@
if fids.is_a?( Array ) and fids.length > 0
fids.each { |id|
fid = lookupField( id )
if fid
fname = lookupFieldNameFromID( id )
- @fnames = Array.new if @fnames.nil?
+ @fnames ||= []
@fnames << fname
else
raise "verifyFieldList: '#{id}' is not a valid field ID"
end
}
@@ -1160,11 +1183,11 @@
elsif fnames
if fnames.is_a?( Array ) and fnames.length > 0
fnames.each { |name|
fid = lookupFieldIDByName( name )
if fid
- @fids = Array.new if @fids.nil?
+ @fids ||= []
@fids << fid
else
raise "verifyFieldList: '#{name}' is not a valid field name"
end
}
@@ -1228,12 +1251,12 @@
# Returns a valid query operator.
def verifyQueryOperator( operator, fieldType )
queryOperator = ""
if @queryOperators.nil?
- @queryOperators = Hash.new
- @queryOperatorFieldType = Hash.new
+ @queryOperators = {}
+ @queryOperatorFieldType = {}
@queryOperators[ "CT" ] = [ "contains", "[]" ]
@queryOperators[ "XCT" ] = [ "does not contain", "![]" ]
@queryOperators[ "EX" ] = [ "is", "==", "eq" ]
@@ -1286,20 +1309,24 @@
queryOperator
end
# Get a field's base type using its name.
def lookupBaseFieldTypeByName( fieldName )
+ type = ""
fid = lookupFieldIDByName( fieldName )
field = lookupField( fid ) if fid
type = field.attributes[ "base_type" ] if field
+ type
end
# Get a field's type using its name.
def lookupFieldTypeByName( fieldName )
+ type = ""
fid = lookupFieldIDByName( fieldName )
field = lookupField( fid ) if fid
type = field.attributes[ "field_type" ] if field
+ type
end
# Returns the string required for emebedding CSV data in a request.
def formatImportCSV( csv )
"<![CDATA[#{csv}]]>"
@@ -1436,11 +1463,11 @@
end
# Converts a string into an array, given a field separator.
# '"' followed by the field separator are treated the same way as just the field separator.
def splitString( string, fieldSeparator = "," )
- ra = Array.new
+ ra = []
string.chomp!
if string.include?( "\"" )
a=string.split( "\"#{fieldSeparator}" )
a.each{ |b| c=b.split( "#{fieldSeparator}\"" )
c.each{ |d|
@@ -1454,11 +1481,11 @@
end
# Returns the URL-encoded version of a non-printing character.
def escapeXML( char )
if @xmlEscapes.nil?
- @xmlEscapes = Hash.new
+ @xmlEscapes = {}
(0..255).each{ |i| @xmlEscapes[ i.chr ] = sprintf( "&#%03d;", i ) }
end
return @xmlEscapes[ char ] if @xmlEscapes[ char ]
char
end
@@ -1554,14 +1581,14 @@
onSetActiveField } if @events.nil?
if @events.include?( event )
if handler and handler.is_a?( EventHandler )
if @eventSubscribers.nil?
- @eventSubscribers = Hash.new
+ @eventSubscribers = {}
end
if not @eventSubscribers.include?( event )
- @eventSubscribers[ event ] = Array.new
+ @eventSubscribers[ event ] = []
end
if not @eventSubscribers[ event ].include?( handler )
@eventSubscribers[ event ] << handler
end
else
@@ -1739,11 +1766,11 @@
end
# API_DeleteAppZip
def deleteAppZip( dbid )
@dbid = dbid
- sendRequest( :deleteAppZip, xmlRequestData )
+ sendRequest( :deleteAppZip )
return self if @chainAPIcalls
@responseCode
end
# API_DumpAppZip
@@ -1862,11 +1889,11 @@
end
# API_ChangeRecordOwner
def _changeRecordOwner( rid, newowner ) changeRecordOwner( @dbid, rid, newowner ) end
- # API_ChangeUserRole, using the active table id.
+ # API_ChangeUserRole.
def changeUserRole( dbid, userid, roleid, newroleid )
@dbid, @userid, @roleid, @newroleid = dbid, userid, roleid, newroleid
xmlRequestData = toXML( :userid, @userid )
xmlRequestData << toXML( :roleid, @roleid )
@@ -2025,12 +2052,16 @@
@variables = getResponseElements( "qdbapi/variable" )
end
return self if @chainAPIcalls
- if @records and block_given?
- @records.each { |element| yield element }
+ if block_given?
+ if @records
+ @records.each { |element| yield element }
+ else
+ yield nil
+ end
else
@records
end
end
@@ -2069,22 +2100,22 @@
return self if @chainAPIcalls
@numMatches
end
- # API_DoQuery, using the active table id.
+ # API_DoQueryCount, using the active table id.
def _doQueryCount( query ) doQueryCount( @dbid, query ) end
# Download a file's contents from a file attachment field in QuickBase.
# You must write the contents to disk before a local file exists.
def downLoadFile( dbid, rid, fid, vid = "0" )
@dbid, @rid, @fid, @vid = dbid, rid, fid, vid
@downLoadFileURL = "http://#{@org}.#{@domain}.com/up/#{dbid}/a/r#{rid}/e#{fid}/v#{vid}"
- if @httpConnection.use_ssl?
+ if @useSSL
@downLoadFileURL.gsub!( "http:", "https:" )
end
@requestHeaders = { "Cookie" => "ticket=#{@ticket}" }
@@ -2095,12 +2126,18 @@
p @requestHeaders
end
begin
- @responseCode, @fileContents = @httpConnection.get( @downLoadFileURL, @requestHeaders )
-
+ if USING_HTTPCLIENT
+ response = @httpConnection.get( @downLoadFileURL, nil, @requestHeaders )
+ @responseCode = response.status
+ @fileContents = response.body.content if response.body
+ else
+ @responseCode, @fileContents = @httpConnection.get( @downLoadFileURL, @requestHeaders )
+ end
+
rescue Net::HTTPBadResponse => @lastError
rescue Net::HTTPHeaderSyntaxError => @lastError
rescue StandardError => @lastError
end
@@ -2360,10 +2397,11 @@
# API_GetDBPage
def getDBPage( dbid, pageid, pagename = nil )
@dbid, @pageid, @pagename = dbid, pageid, pagename
+ xmlRequestData = nil
if @pageid
xmlRequestData = toXML( :pageid, @pageid )
elsif @pagename
xmlRequestData = toXML( :pagename, @pagename )
else
@@ -2681,11 +2719,11 @@
# API_ImportFromCSV
def importFromCSV( dbid, records_csv, clist, skipfirst = nil, msInUTC = nil )
@dbid, @records_csv, @clist, @skipfirst, @msInUTC = dbid, records_csv, clist, skipfirst, msInUTC
- @clist = @clist ? @clist : "0"
+ @clist ||= "0"
xmlRequestData = toXML( :records_csv, @records_csv )
xmlRequestData << toXML( :clist, @clist )
xmlRequestData << toXML( :skipfirst, "1" ) if @skipfirst
xmlRequestData << toXML( :msInUTC, "1" ) if @msInUTC
@@ -2724,12 +2762,16 @@
sendRequest( :listDBPages )
@pages = getResponseValue( :pages )
return self if @chainAPIcalls
- if @pages and block_given?
- @pages.each{ |element| yield element }
+ if block_given?
+ if @pages
+ @pages.each{ |element| yield element }
+ else
+ yield nil
+ end
else
@pages
end
end
@@ -2839,11 +2881,11 @@
xmlRequestData = toXML( :appdata , @appdata )
sendRequest( :setAppData )
return self if @chainAPIcalls
- return @appdata
+ @appdata
end
# API_SetAppData, using the active table id.
def _setAppData( appdata ) setAppData( @dbid, appdata ) end
@@ -3194,35 +3236,35 @@
def getAllValuesForFields( dbid, fieldNames = nil, query = nil, qid = nil, qname = nil, clist = nil, slist = nil, fmt = "structured", options = nil )
if dbid
getSchema(dbid)
- values = Hash.new
- fieldIDs = Hash.new
+ values = {}
+ fieldIDs = {}
if fieldNames and fieldNames.is_a?( String )
- values[ fieldNames ] = Array.new
+ values[ fieldNames ] = []
fieldID = lookupFieldIDByName( fieldNames )
if fieldID
fieldIDs[ fieldNames ] = fieldID
elsif fieldNames.match(/[0-9]+/) # assume fieldNames is a field ID
fieldIDs[ fieldNames ] = fieldNames
end
elsif fieldNames and fieldNames.is_a?( Array )
fieldNames.each{ |name|
if name
- values[ name ] = Array.new
+ values[ name ] = []
fieldID = lookupFieldIDByName( name )
if fieldID
fieldIDs[ fieldID ] = name
elsif name.match(/[0-9]+/) # assume name is a field ID
fieldIDs[ name ] = name
end
end
}
elsif fieldNames.nil?
getFieldNames(dbid).each{|name|
- values[ name ] = Array.new
+ values[ name ] = []
fieldID = lookupFieldIDByName( name )
fieldIDs[ fieldID ] = name
}
end
@@ -3339,11 +3381,11 @@
queryResults = getAllValuesForFields(dbid,fieldNames,query,qid,qname,clist,slist,fmt,options)
if queryResults
numRecords = 0
numRecords = queryResults[fieldNames[0]].length if queryResults[fieldNames[0]]
(0..(numRecords-1)).each{|recNum|
- recordHash = Hash.new
+ recordHash = {}
fieldNames.each{|fieldName|
recordHash[fieldName]=queryResults[fieldName][recNum]
}
yield recordHash
}
@@ -3354,12 +3396,12 @@
end
# Same as iterateRecords but with fields optionally filtered by Ruby regular expressions.
# e.g. iterateFilteredRecords( "dhnju5y7", [{"Name" => "[A-E].+}","Address"] ) { |values| puts values["Name"], values["Address"] }
def iterateFilteredRecords( dbid, fieldNames, query = nil, qid = nil, qname = nil, clist = nil, slist = nil, fmt = "structured", options = nil )
- fields = Array.new
- regexp = Hash.new
+ fields = []
+ regexp = {}
fieldNames.each{|field|
if field.is_a?(Hash)
fields << field.keys[0]
regexp[field.keys[0]] = field.values[0]
elsif field.is_a?(String)
@@ -3401,14 +3443,14 @@
raise "'iterateJoinRecords' must be called with a block." if not block_given?
if tablesAndFields and tablesAndFields.is_a?(Array)
# get all the records from QuickBase that we might need - fewer API calls is faster than processing extra data
- tables = Array.new
- numRecords = Hash.new
- tableRecords = Hash.new
- joinfield = Hash.new
+ tables = []
+ numRecords = {}
+ tableRecords = {}
+ joinfield = {}
tablesAndFields.each{|tableAndFields|
if tableAndFields and tableAndFields.is_a?(Hash)
if tableAndFields["dbid"] and tableAndFields["fields"] and tableAndFields["joinfield"]
if tableAndFields["fields"].is_a?(Array)
@@ -3443,14 +3485,14 @@
# get the value of the join field in each record of the first table
joinfieldValue = tableRecords[tables[0]][joinfield[tables[0]]][i]
# save the other tables' record indices of records containing the joinfield value
- tableIndices = Array.new
+ tableIndices = []
(1..(numTables-1)).each{|tableNum|
- tableIndices[tableNum] = Array.new
+ tableIndices[tableNum] = []
(0..(numRecords[tables[tableNum]]-1)).each{|j|
if joinfieldValue == tableRecords[tables[tableNum]][joinfield[tables[tableNum]]][j]
tableIndices[tableNum] << j
end
}
@@ -3462,18 +3504,18 @@
buildJoinRecord = false if not tableIndices[tableNum].length > 0
}
if buildJoinRecord
- joinRecord = Hash.new
+ joinRecord = {}
tableRecords[tables[0]].each_key{|field|
joinRecord[field] = tableRecords[tables[0]][field][i]
}
# nested loops for however many tables we have
- currentIndex = Array.new
+ currentIndex = []
numTables.times{ currentIndex << 0 }
loop {
(1..(numTables-1)).each{|tableNum|
index = tableIndices[tableNum][currentIndex[tableNum]]
tableRecords[tables[tableNum]].each_key{|field|
@@ -3519,11 +3561,11 @@
raise "'iterateUnionRecords' must be called with a block." if not block_given?
if tables and tables.is_a?(Array)
if fieldNames and fieldNames.is_a?(Array)
- tableRecords = Array.new
+ tableRecords = []
tables.each{|table|
if table and table.is_a?(Hash) and table["dbid"]
tableRecords << getAllValuesForFields( table["dbid"],
fieldNames,
table["query"],
@@ -3541,17 +3583,17 @@
raise "'fieldNames' must be an Array of field names valid in all the tables."
end
else
raise "'tables' must be an Array of Hashes."
end
- usedRecords = Hash.new
+ usedRecords = {}
tableRecords.each{|queryResults|
if queryResults
numRecords = 0
numRecords = queryResults[fieldNames[0]].length if queryResults[fieldNames[0]]
(0..(numRecords-1)).each{|recNum|
- recordHash = Hash.new
+ recordHash = {}
fieldNames.each{|fieldName|
recordHash[fieldName]=queryResults[fieldName][recNum]
}
if not usedRecords[recordHash.values.join]
usedRecords[recordHash.values.join]=true
@@ -3585,15 +3627,15 @@
def iterateSummaryRecords( dbid, fieldNames,query = nil, qid = nil, qname = nil, clist = nil, slist = nil, fmt = "structured", options = nil )
getSchema(dbid)
slist = ""
- summaryRecord = Hash.new
- doesTotal = Hash.new
- doesAverage = Hash.new
- summaryField = Hash.new
- fieldType = Hash.new
+ summaryRecord = {}
+ doesTotal = {}
+ doesAverage = {}
+ summaryField = {}
+ fieldType = {}
fieldNames.each{ |fieldName|
fieldType[fieldName] = lookupFieldTypeByName(fieldName)
isSummaryField = true
doesTotal[fieldName] = isTotalField?(fieldName)
@@ -3640,11 +3682,11 @@
}
yield summaryRecord
count=0
- summaryRecord = Hash.new
+ summaryRecord = {}
fieldNames.each{|fieldName|
if doesTotal[fieldName]
summaryRecord["#{fieldName}:Total"] = 0
end
if doesAverage[fieldName]
@@ -3811,11 +3853,11 @@
end
# Find the lowest value for one or more fields in the records returned by a query.
# e.g. minimumsHash = min("dfdfafff",["Date Sent","Quantity","Part Name"])
def min( dbid, fieldNames, query = nil, qid = nil, qname = nil, clist = nil, slist = nil, fmt = "structured", options = nil )
- min = Hash.new
+ min = {}
hasValues = false
iterateRecords(dbid,fieldNames,query,qid,qname,clist,slist,fmt,options){|record|
fieldNames.each{|field|
value = record[field]
if value
@@ -3838,11 +3880,11 @@
end
# Find the highest value for one or more fields in the records returned by a query.
# e.g. maximumsHash = max("dfdfafff",["Date Sent","Quantity","Part Name"])
def max( dbid, fieldNames, query = nil, qid = nil, qname = nil, clist = nil, slist = nil, fmt = "structured", options = nil )
- max = Hash.new
+ max = {}
hasValues = false
iterateRecords(dbid,fieldNames,query,qid,qname,clist,slist,fmt,options){|record|
fieldNames.each{|field|
value = record[field]
if value
@@ -3865,11 +3907,11 @@
end
# Returns the number non-null values for one or more fields in the records returned by a query.
# e.g. countsHash = count("dfdfafff",["Date Sent","Quantity","Part Name"])
def count( dbid, fieldNames, query = nil, qid = nil, qname = nil, clist = nil, slist = nil, fmt = "structured", options = nil )
- count = Hash.new
+ count = {}
fieldNames.each{|field| count[field]=0 }
hasValues = false
iterateRecords(dbid,fieldNames,query,qid,qname,clist,slist,fmt,options){|record|
fieldNames.each{|field|
if record[field] and record[field].length > 0
@@ -3883,11 +3925,11 @@
end
# Returns the sum of the values for one or more fields in the records returned by a query.
# e.g. sumsHash = sum("dfdfafff",["Date Sent","Quantity","Part Name"])
def sum( dbid, fieldNames, query = nil, qid = nil, qname = nil, clist = nil, slist = nil, fmt = "structured", options = nil )
- sum = Hash.new
+ sum = {}
hasValues = false
iterateRecords(dbid,fieldNames,query,qid,qname,clist,slist,fmt,options){|record|
fieldNames.each{|field|
value = record[field]
if value
@@ -3912,13 +3954,13 @@
end
# Returns the average of the values for one or more fields in the records returned by a query.
# e.g. averagesHash = average("dfdfafff",["Date Sent","Quantity","Part Name"])
def average( dbid, fieldNames, query = nil, qid = nil, qname = nil, clist = nil, slist = nil, fmt = "structured", options = nil )
- count = Hash.new
+ count = {}
fieldNames.each{|field| count[field]=0 }
- sum = Hash.new
+ sum = {}
iterateRecords(dbid,fieldNames,query,qid,qname,clist,slist,fmt,options){|record|
fieldNames.each{|field|
value = record[field]
if value
baseFieldType = lookupBaseFieldTypeByName(field)
@@ -3935,11 +3977,11 @@
end
count[field] += 1
end
}
}
- average = Hash.new
+ average = {}
hasValues = false
fieldNames.each{|field|
if sum[field] and count[field] > 0
average[field] = (sum[field]/count[field])
hasValues = true
@@ -4007,11 +4049,11 @@
elsif not fid
raise "'fieldName' or 'fid' must be specified"
end
field = lookupField( fid )
if field
- choices = Array.new
+ choices = []
choicesProc = proc { |element|
if element.is_a?(REXML::Element)
if element.name == "choice" and element.has_text?
choices << element.text
end
@@ -4026,11 +4068,11 @@
end
# Get an array of all the record IDs for a specified table.
# e.g. IDs = getAllRecordIDs( "dhnju5y7" ){ |id| puts "Record #{id}" }
def getAllRecordIDs( dbid )
- rids = Array.new
+ rids = []
if dbid
getSchema( dbid )
next_record_id = getResponseElement( "table/original/next_record_id" )
if next_record_id and next_record_id.has_text?
next_record_id = next_record_id.text
@@ -4053,34 +4095,34 @@
# Finds records with the same values in a specified list of fields.
# The field list may be a list of field IDs or a list of field names.
# Returns a hash with the structure { "duplicated values" => [ rid, rid, ... ] }
def findDuplicateRecordIDs( fnames, fids, dbid = @dbid, ignoreCase = true )
verifyFieldList( fnames, fids, dbid )
- duplicates = Hash.new
+ duplicates = {}
if @fids
cslist = @fids.join( "." )
ridFields = lookupFieldsByType( "recordid" )
if ridFields and ridFields.last
cslist << "."
recordidFid = ridFields.last.attributes["id"]
cslist << recordidFid
- valuesUsed = Hash.new
+ valuesUsed = {}
doQuery( @dbid, nil, nil, nil, cslist ) { |record|
next unless record.is_a?( REXML::Element) and record.name == "record"
recordID = ""
- recordValues = Array.new
+ recordValues = []
record.each { |f|
if f.is_a?( REXML::Element) and f.name == "f" and f.has_text?
if recordidFid == f.attributes["id"]
recordID = f.text
else
recordValues << f.text
end
end
}
if not valuesUsed[ recordValues ]
- valuesUsed[ recordValues ] = Array.new
+ valuesUsed[ recordValues ] = []
end
valuesUsed[ recordValues ] << recordID
}
valuesUsed.each{ |valueArray, recordArray|
@@ -4106,11 +4148,11 @@
def deleteDuplicateRecords( fnames, fids = nil, options = nil, dbid = @dbid )
num_deleted = 0
if options and not options.is_a?( Hash )
raise "deleteDuplicateRecords: 'options' parameter must be a Hash"
else
- options = Hash.new
+ options = {}
options[ "keeplastrecord" ] = true
options[ "ignoreCase" ] = true
end
findDuplicateRecordIDs( fnames, fids, dbid, options[ "ignoreCase" ] ) { |dupeValues, recordIDs|
if options[ "keeplastrecord" ]
@@ -4130,11 +4172,11 @@
if field.elements[ "fid" ].text.to_i > 5 #skip built-in fields
addFieldValuePair( field.elements[ "name" ].text, nil, nil, field.elements[ "value" ].text )
end
end
}
- newRecordIDs = Array.new
+ newRecordIDs = []
if @fvlist and @fvlist.length > 0
numCopies.times {
addRecord( dbid, @fvlist )
newRecordIDs << @rid if @rid and @update_id
}
@@ -4184,11 +4226,11 @@
workbook.Close
excel.Quit
csvData = ""
- targetFieldIDs = Array.new
+ targetFieldIDs = []
if fieldNames and fieldNames.length > 0
fieldNames.each{ |fieldNameRow|
fieldNameRow.each{ |fieldName|
if fieldName
@@ -4259,22 +4301,22 @@
num_recs_imported = 0
if FileTest.readable?( filename )
if dbid
getSchema( dbid )
- targetFieldIDs = Array.new
+ targetFieldIDs = []
if targetFieldNames and targetFieldNames.is_a?( Array )
targetFieldNames.each{ |fieldName|
targetFieldIDs << lookupFieldIDByName( fieldName )
}
return 0 if targetFieldIDs.length != targetFieldNames.length
end
useAddRecord = false
- invalidLines = Array.new
- validLines = Array.new
+ invalidLines = []
+ validLines = []
linenum = 1
IO.foreach( filename ){ |line|
if fieldSeparator != "," and line.index( "," )
@@ -4435,10 +4477,22 @@
# Update the file attachment in an existing record in the active record in the active table.
# e.g. _updateFile( "contacts.txt", "Contacts File" )
def _updateFile( filename, fileAttachmentFieldName )
updateFile( @dbid, @rid, filename, fileAttachmentFieldName )
end
+
+ # Remove the file from a File Attachment field in an existing record.
+ # e.g. removeFileAttachment( "bdxxxibz4", "6", "Document" )
+ def removeFileAttachment( dbid, rid , fileAttachmentFieldName )
+ updateFile( dbid, rid, "delete", fileAttachmentFieldName )
+ end
+
+ # Remove the file from a File Attachment field in an existing record in the active table
+ # e.g. _removeFileAttachment( "6", "Document" )
+ def _removeFileAttachment( rid , fileAttachmentFieldName )
+ updateFile( @dbid, rid, "delete", fileAttachmentFieldName )
+ end
# Translate a simple SQL SELECT statement to a QuickBase query and run it.
#
# If any supplied field names are numeric, they will be treated as QuickBase field IDs if
# they aren't valid field names.
@@ -4455,18 +4509,18 @@
dbid = nil
clist = nil
slist = nil
state = nil
dbname = ""
- columns = Array.new
- sortFields = Array.new
+ columns = []
+ sortFields = []
limit = nil
offset = nil
options = nil
getRecordCount = false
- queryFields = Array.new
+ queryFields = []
query = "{'["
queryState = "getFieldName"
queryField = ""
sql.split(' ').each{ |token|
@@ -4772,11 +4826,11 @@
end
recordid
end
- # Iterate @records XML and yield only <record> elements.
+ # Iterate @records XML and yield only 'record' elements.
def eachRecord( records = @records )
if records and block_given?
records.each { |record|
if record.is_a?( REXML::Element) and record.name == "record"
@record = record
@@ -4785,10 +4839,10 @@
}
end
nil
end
- # Iterate record XML and yield only <f> elements.
+ # Iterate record XML and yield only 'f' elements.
def eachField( record = @record )
if record and block_given?
record.each{ |field|
if field.is_a?( REXML::Element) and field.name == "f" and field.attributes["id"]
@field = field