advantage_quickbase 0.1

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