advantage_quickbase 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.
- data/lib/quickbase.rb +181 -0
- metadata +46 -0
data/lib/quickbase.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'json'
|
4
|
+
require 'csv'
|
5
|
+
|
6
|
+
module Quickbase
|
7
|
+
class API
|
8
|
+
def initialize( domain, username, password, app_token=nil )
|
9
|
+
@domain = domain
|
10
|
+
|
11
|
+
data = {
|
12
|
+
username: username,
|
13
|
+
password: password,
|
14
|
+
apptoken: app_token
|
15
|
+
}
|
16
|
+
request_xml = build_request_xml( data )
|
17
|
+
|
18
|
+
@http = Net::HTTP.new( base_url, 443 )
|
19
|
+
@http.use_ssl = true
|
20
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
21
|
+
|
22
|
+
url = build_request_url( :authenticate )
|
23
|
+
headers = build_request_headers( :authenticate, request_xml )
|
24
|
+
|
25
|
+
result = @http.post( url, request_xml, headers )
|
26
|
+
parsed_result = parse_xml( result.body )
|
27
|
+
|
28
|
+
ticket = get_tag_value( parsed_result, :ticket )
|
29
|
+
if ticket
|
30
|
+
@ticket = ticket
|
31
|
+
else
|
32
|
+
raise "Connection Failed\n\n#{result.body}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def do_query_count( db_id, query )
|
37
|
+
result = send_request( :doQueryCount, db_id, {query: query} )
|
38
|
+
get_tag_value( result, :nummatches ).to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
def do_query( db_id, options )
|
42
|
+
# Define the query format
|
43
|
+
if !options[ :fmt ]
|
44
|
+
options[ :fmt ] = 'structured'
|
45
|
+
end
|
46
|
+
|
47
|
+
# Normalize the field list variables into period-separated strings
|
48
|
+
options[ :clist ] = normalize_list( options[:clist] )
|
49
|
+
options[ :slist ] = normalize_list( options[:slist] )
|
50
|
+
|
51
|
+
result = send_request( :doQuery, db_id, options )
|
52
|
+
|
53
|
+
return_json = []
|
54
|
+
result.css( 'record' ).each do |record|
|
55
|
+
json_record = {}
|
56
|
+
record.css( 'f' ).each do |field|
|
57
|
+
json_record[ field['id'] ] = field.text
|
58
|
+
end
|
59
|
+
|
60
|
+
return_json << json_record
|
61
|
+
end
|
62
|
+
|
63
|
+
return_json
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_record( db_id, new_values )
|
67
|
+
xml = build_update_xml( new_values )
|
68
|
+
result = send_request( :addRecord, db_id, nil, xml )
|
69
|
+
|
70
|
+
get_tag_value( result, :rid )
|
71
|
+
end
|
72
|
+
|
73
|
+
def edit_record( db_id, record_id, new_values )
|
74
|
+
xml = build_update_xml( new_values, record_id )
|
75
|
+
result = send_request( :editRecord, db_id, nil, xml )
|
76
|
+
|
77
|
+
get_tag_value( result, :rid ).to_s == record_id.to_s
|
78
|
+
end
|
79
|
+
|
80
|
+
def delete_record( db_id, record_id )
|
81
|
+
result = send_request( :deleteRecord, db_id, {rid: record_id} )
|
82
|
+
|
83
|
+
get_tag_value( result, :rid ).to_s == record_id.to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
def import_from_csv( db_id, data_array, columns )
|
87
|
+
columns = normalize_list( columns )
|
88
|
+
xml = build_csv_xml( data_array, columns )
|
89
|
+
|
90
|
+
result = send_request( :importFromCSV, db_id, nil, xml )
|
91
|
+
result.css('rid').map{ |xml_node| xml_node.text.to_i }
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
def normalize_list( list )
|
96
|
+
if list.is_a?( Array )
|
97
|
+
list = list.map { |fid| fid.to_s }.join( '.' )
|
98
|
+
end
|
99
|
+
list
|
100
|
+
end
|
101
|
+
|
102
|
+
def build_request_headers( api_call, request_body )
|
103
|
+
{
|
104
|
+
'Content-Type' => 'application/xml',
|
105
|
+
'Content-Length' => request_body.length.to_s,
|
106
|
+
'QUICKBASE-ACTION' => "API_#{api_call}"
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
def build_request_url( api_call, db_id=nil )
|
111
|
+
url = base_url
|
112
|
+
|
113
|
+
# Different calls have different API paths. Assign those here
|
114
|
+
case api_call
|
115
|
+
when :authenticate
|
116
|
+
url += '/db/main'
|
117
|
+
else
|
118
|
+
url += "/db/#{db_id}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def base_url
|
123
|
+
"https://#{@domain}.quickbase.com"
|
124
|
+
end
|
125
|
+
|
126
|
+
def build_request_xml( tags )
|
127
|
+
xml = '<qdbapi>'
|
128
|
+
xml += tags.map{ |name, value| "<#{name}>#{value}</#{name}>" }.join()
|
129
|
+
xml += "<ticket>#{@ticket}</ticket>"
|
130
|
+
xml += '</qdbapi>'
|
131
|
+
end
|
132
|
+
|
133
|
+
def build_update_xml( new_values, record_id=nil )
|
134
|
+
xml = '<qdbapi>'
|
135
|
+
if record_id
|
136
|
+
xml += "<key>#{record_id}</key>"
|
137
|
+
end
|
138
|
+
xml += new_values.map { |field_id, value| "<field fid='#{field_id}'>#{value}</field>" }.join()
|
139
|
+
xml += "<ticket>#{@ticket}</ticket>"
|
140
|
+
xml += '</qdbapi>'
|
141
|
+
end
|
142
|
+
|
143
|
+
def build_csv_xml( new_values, fields_to_import )
|
144
|
+
xml = '<qdbapi>'
|
145
|
+
xml += "<records_csv><![CDATA[\n"
|
146
|
+
xml += new_values.map{ |line| CSV.generate_line(line) }.join()
|
147
|
+
xml += "]]></records_csv>"
|
148
|
+
xml += "<clist>#{fields_to_import}</clist>"
|
149
|
+
xml += "<ticket>#{@ticket}</ticket>"
|
150
|
+
xml += '</qdbapi>'
|
151
|
+
end
|
152
|
+
|
153
|
+
def parse_xml( xml )
|
154
|
+
Nokogiri::HTML( xml )
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_tag_value( xml, tag_name )
|
158
|
+
tag = xml.css( tag_name.to_s )
|
159
|
+
tag_value = nil
|
160
|
+
if !tag.empty?
|
161
|
+
tag_value = tag.text
|
162
|
+
end
|
163
|
+
|
164
|
+
tag_value
|
165
|
+
end
|
166
|
+
|
167
|
+
def send_request( api_call, db_id, request_data, request_xml=nil )
|
168
|
+
# Format request data hash into xml
|
169
|
+
if request_data && !request_xml
|
170
|
+
request_xml = build_request_xml( request_data )
|
171
|
+
end
|
172
|
+
|
173
|
+
url = build_request_url( api_call, db_id )
|
174
|
+
headers = build_request_headers( api_call, request_xml )
|
175
|
+
|
176
|
+
result = @http.post( url, request_xml, headers )
|
177
|
+
|
178
|
+
parse_xml( result.body )
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: advantage_quickbase
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ben Roux
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-04-03 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Concise implementation of select Quickbase API functions
|
15
|
+
email: liquid.ise@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/quickbase.rb
|
21
|
+
homepage: https://github.com/liquidise/Quickbase-Gem
|
22
|
+
licenses:
|
23
|
+
- MIT
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 1.8.25
|
43
|
+
signing_key:
|
44
|
+
specification_version: 3
|
45
|
+
summary: Quickbase API gem
|
46
|
+
test_files: []
|