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.
Files changed (2) hide show
  1. data/lib/quickbase.rb +181 -0
  2. 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: []