openapply 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,15 +10,11 @@ pry
10
10
 
11
11
  and run this code (or play )
12
12
  ```ruby
13
- require 'pp'
14
13
  require 'openapply'
15
- require_relative './demo_site'
16
-
17
14
 
18
15
  # BASIC USAGE (see readme)
19
16
  # use the .rbenv-vars for a simple setup
20
17
  @oa = Openapply::Client.new()
21
- @oa.one_student_record_by_id(95)
22
18
 
23
19
  # see settings
24
20
  @oa.api_url
@@ -26,31 +22,91 @@ require_relative './demo_site'
26
22
  @oa.base_path
27
23
  @oa.api_timeout
28
24
  @oa.api_reply_count
29
- # replace record_count with reply count
30
- # @oa.reply_count
25
+
26
+
27
+ # student summarys with applied status
28
+ summaries = @oa.students_by_status('applied')
29
+ student_ids = @oa.student_ids_by_status('applied')
30
+
31
+ ids = student_ids[:student_ids]
32
+
33
+
34
+ # first student details - return data as is
35
+ details = @oa.student_details_by_id(ids.first)
36
+
37
+ # last applied student details - custom fields -
38
+ # top level & duplicate :parent removed
39
+ flattened = @oa.student_details_by_id(ids.last, [:custom_fields], [:parent_guardian])
40
+
41
+ # get first 5 records with status applied with student_ids greater than the last
42
+ # two records (which should return last six students) - but response is limited to 5
43
+ # updated after 5th of Nov 2016
44
+ custom = @oa.students_query('applied', ids[-7] , '2016-11-05', 5)
45
+
46
+
47
+ # get students with applied and enrolled status, flatten no fields,
48
+ # remove the parent_guardian (duplicate) info,
49
+ # move into the xlsx file the following data: studnet id and student name
50
+ # parent address (line 1) and country, and no payment info
51
+ csv = @oa.students_as_csv_by_status( 'applied', nil, [:parent_guardian],
52
+ [:id, :name], {keys: [:address, :country]}, nil )
53
+ #
54
+ @oa.send_data_to_remote_server( csv, ENV['REMOTE_HOSTNAME'],
55
+ ENV['REMOTE_USERNAME'], "#{ENV['REMOTE_PATH_FILE']}.csv", ENV['REMOTE_PERMISSIONS'])
56
+ # save csv string as a file locally
57
+ open('test_file.csv', 'w') { |f| f.puts csv }
58
+
59
+ # get students with applied and enrolled status, flatten the custom_fields,
60
+ # remove the parent_guardian (duplicate) info,
61
+ # move into the xlsx file the following data: studnet id and student name
62
+ # parent address (line 1) and country, and the oldest three payment amounts & dates
63
+ xlsx = @oa.students_as_xlsx_by_status(['applied','accepted'], [:custom_fields],
64
+ [:parent_guardian], [:id, :name],
65
+ {count: 2, keys: [:address, :country]},
66
+ {count: , order: :oldest, keys: [:amount, :date]})
67
+ #
68
+ @oa.send_data_to_remote_server( xlsx, ENV['REMOTE_HOSTNAME'],
69
+ ENV['REMOTE_USERNAME'], "#{ENV['REMOTE_PATH_FILE']}.xlsx", ENV['REMOTE_PERMISSIONS'])
70
+ # save as a xlsx file locally
71
+ xlsx.serialize('test_file.xlsx')
72
+
31
73
  ```
32
74
 
33
75
  * or More advanced - multiple OA sites
34
76
  ```ruby
35
77
 
36
- require 'pp'
78
+ # require 'pp'
37
79
  require 'openapply'
38
80
  require_relative './demo_site'
39
81
 
40
82
  # use a class override in order to interact with multiple oa sites
41
- @demo = DemoSite.new()
83
+ # or extend functionality
84
+ @mine = MySite.new()
85
+
86
+
87
+ # get students with applied and enrolled status, flatten no fields,
88
+ # remove the parent_guardian (duplicate) info,
89
+ # move into the xlsx file the following data: studnet id and student name
90
+ # parent address (line 1) and country, and no payment info
91
+ @mine.records_as_csv_to_file( 'applied', nil, [:parent_guardian], [:id, :name],
92
+ {keys: [:address, :country]}, nil , 'test.csv' )
42
93
 
43
- # get 5 summary records
44
- hash = @demo.custom_student_summaries('applied', nil, nil, 5)
94
+ @mine.records_as_csv_to_server( 'applied', nil, [:parent_guardian], [:id, :name],
95
+ {keys: [:address, :country]}, nil )
45
96
 
46
- # get all students
47
- hash = students_by_status('applied')
48
- array = @demo.students_hash_to_students_array(hash)
49
- csv_1 = @demo.students_array_into_csv_string(array)
50
- # @demo.send_csv_to_server(csv_1, 'host.example.io', 'user', '/home/user/file1.csv')
97
+ # get students with applied and enrolled status, flatten the custom_fields,
98
+ # remove the parent_guardian (duplicate) info,
99
+ # move into the xlsx file the following data: studnet id and student name
100
+ # parent address (line 1) and country, and the oldest three payment amounts & dates
101
+ @mine.records_as_xlsx_to_file( ['applied','enrolled'], [:custom_fields],
102
+ [:parent_guardian], [:id, :name],
103
+ {count: 2, keys: [:address, :country]},
104
+ {count: 3, order: :oldest, keys: [:amount, :date]}, 'test.xlsx')
51
105
 
52
- # SLOW takes minutes
53
- csv_2 = @demo.student_ids_names_by_status_to_csv('applied')
54
- # @demo.send_csv_to_server(csv_2, 'host.example.io', 'user', '/home/user/file2.csv')
106
+ @mine.records_as_xlsx_to_server(['applied','enrolled'], [:custom_fields],
107
+ [:parent_guardian], [:id, :name],
108
+ {count: 2, keys: [:address, :country]},
109
+ {count: 3, order: :newest, keys: [:amount, :date]})
55
110
 
111
+ # use cron or other similar tools to automate these processes
56
112
  ```
@@ -1,94 +1,60 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'csv'
4
- require 'net/scp'
5
- require 'stringio'
6
3
  require 'httparty'
7
4
 
8
- class DemoSite < Openapply::Client
5
+ class MySite < Openapply::Client
9
6
  include HTTParty
10
7
 
11
- # these next two are needed in a subclass to interact with multiple OA sites
12
- localized_url = ENV['OA_BASE_URI']
8
+ # add customized site info
9
+ # (say you need to use both: demo.openapply.com and my.openapply.com) --
10
+ # this class defines my.openapply.com and its special needs
11
+ localized_url = ENV['MY_BASE_URI']
13
12
  base_uri localized_url
14
13
 
15
14
  def api_key
16
- ENV['OA_AUTH_TOKEN']
15
+ ENV['MY_AUTH_TOKEN']
17
16
  end
18
17
 
19
- # Business logic: create a csv file of a given status & transfer it
20
-
21
- def student_ids_names_by_status_to_csv(status)
22
- # best is to check if status is in the list of valid statuses
23
- return { error: "no status"} if status.to_s.eql? ""
24
-
25
- # # this next step is slow (for 100 kids) - investigate
26
- # student_hash = all_students_all_data_by_status(status)
27
- student_hash = students_by_status(status)
28
-
29
-
30
- student_array = students_hash_to_students_array(student_hash)
31
- student_csv = students_array_into_csv_string(student_array)
18
+ # defines remote host to recieve openapply data
19
+ REMOTE_HOSTNAME = ENV['REMOTE_HOSTNAME'].freeze
20
+ REMOTE_USERNAME = ENV['REMOTE_USERNAME'].freeze
21
+ REMOTE_PATH_FILE = ENV['REMOTE_PATH_FILE'].freeze
22
+ REMOTE_PERMISSIONS = ENV['REMOTE_PERMISSIONS'].freeze
23
+
24
+ # custom code to prepare my.openapply.com data for remote host recieving data
25
+ def records_as_csv_to_file( status, flatten_keys=[],
26
+ reject_keys=[], student_keys=[],
27
+ guardian_info={}, payment_info={}, file )
28
+ data = students_as_csv_by_status( status, flatten_keys, reject_keys,
29
+ student_keys, guardian_info, payment_info)
30
+ # save csv string as a file
31
+ open(file, 'w') { |f| f.puts data }
32
32
  end
33
33
 
34
- def students_hash_to_students_array(hash)
35
- array = []
36
- csv_keys = [:id, :first_name, :last_name]
37
-
38
- headers = csv_keys.map{|k| k.to_s}
39
- # headers = ['id','first_name','last_name']
40
- puts headers
41
-
42
- array << headers
43
-
44
- # don't loop if hash is empty
45
- return headers if hash.empty?
46
-
47
- hash[:students].each do |record|
48
- row = []
49
- # skip record if empty
50
- # puts "#{record[:record]}\n"
51
- next if record.nil?
52
- next if record.nil?
53
- next if record.empty?
54
-
55
- # find the desired fields and add them to the csv
56
- csv_keys.each{ |key| row << record[key] }
57
-
58
- # add row to the master arrary
59
- array << row
60
- end
61
- return array
34
+ def records_as_csv_to_server( status, flatten_keys=[],
35
+ reject_keys=[], student_keys=[],
36
+ guardian_info={}, payment_info={})
37
+ data = students_as_csv_by_status( status, flatten_keys, reject_keys,
38
+ student_keys, guardian_info, payment_info)
39
+ send_data_to_remote_server( data, REMOTE_HOSTNAME, REMOTE_USERNAME,
40
+ "#{REMOTE_PATH_FILE}.csv", REMOTE_PERMISSIONS)
62
41
  end
63
42
 
64
- def students_array_into_csv_string(array)
65
- return "" if array.nil?
66
- return "" if array.empty?
67
- # https://stackoverflow.com/questions/4822422/output-array-to-csv-in-ruby
68
- csv_string = CSV.generate do |csv|
69
- array.each do |row|
70
- csv << row
71
- end
72
- end
73
- return csv_string
43
+ def records_as_xlsx_to_file( status, flatten_keys=[],
44
+ reject_keys=[], student_keys=[],
45
+ guardian_info={}, payment_info={}, file )
46
+ data = students_as_xlsx_by_status( status, flatten_keys, reject_keys,
47
+ student_keys, guardian_info, payment_info)
48
+ data.serialize(file)
74
49
  end
75
50
 
76
- def send_csv_to_server(csv_string, host_name, user_name, remote_path_n_file)
77
- # https://www.safaribooksonline.com/library/view/ruby-cookbook/0596523696/ch06s15.html
78
- xfer_csv = StringIO.new( csv_string )
79
-
80
- # setup using an SSH KEY instead of password
81
- # http://www.rubydoc.info/github/delano/net-scp/Net/SCP
82
- Net::SCP.start(host_name, user_name) do |scp|
83
- # asynchronous upload; call returns immediately
84
- channel = scp.upload( xfer_csv, remote_path_n_file )
85
- channel.wait
86
- end
87
- # ensure file has proper permissions
88
- Net::SSH.start(host_name, user_name) do |ssh|
89
- # Capture all stderr and stdout output from a remote process
90
- output = ssh.exec!("chmod 0775 #{remote_path_n_file}")
91
- end
51
+ def records_as_xlsx_to_server( status, flatten_keys=[],
52
+ reject_keys=[], student_keys=[],
53
+ guardian_info={}, payment_info={})
54
+ data = students_as_xlsx_by_status( status, flatten_keys, reject_keys,
55
+ student_keys, guardian_info, payment_info)
56
+ send_data_to_remote_server( data, REMOTE_HOSTNAME, REMOTE_USERNAME,
57
+ "#{REMOTE_PATH_FILE}.xlsx", REMOTE_PERMISSIONS)
92
58
  end
93
59
 
94
60
  end
@@ -0,0 +1,371 @@
1
+ require 'csv'
2
+ require 'axlsx'
3
+ require 'net/scp'
4
+ require 'net/ssh'
5
+
6
+ module Convert
7
+
8
+ # Queries by status to get a list of students details of a given status
9
+ # and converts the result to an array with headers (based on keys sent)
10
+ #
11
+ # ==== Attributes
12
+ # * +status+ - hash to convert to an array
13
+ # * +flatten_keys+ - an array of keys to bring to the top level
14
+ # (with this key prepened) -- default (blank does nothing)
15
+ # * +reject_keys+ - an array of keys to remove from the data -- default (blank does nothing)
16
+ # * +student_keys+ - [:id, :name] - include student record keys
17
+ # * +guardian_info+ - include guardian record info {count: 2, keys: [:id, :name]}
18
+ # * +payment_info+ - include payment info {count: 2, order: :newest, keys: [:date, :amount]}
19
+ # * guardian & payment info options:
20
+ # count: 2 -- how many parent or payment records to return)
21
+ # keys: [:id, :date] -- an array of keys of data to return
22
+ # order: :newest -- the order to return payments :newest (most recent first - default) or :oldest
23
+ def students_as_array_by_status(status,
24
+ flatten_keys=[], reject_keys=[],
25
+ student_keys=[],
26
+ guardian_info={}, payment_info={})
27
+ #
28
+ check = check_details_keys_validity(flatten_keys, reject_keys)
29
+ return check unless check.nil? # or check[:error].nil?
30
+ #
31
+ students_hash = students_details_by_status( status,
32
+ flatten_keys, reject_keys)
33
+ #
34
+ students_array = students_hash_to_array( students_hash,
35
+ student_keys, guardian_info, payment_info)
36
+ end
37
+ alias_method :students_as_array_by_statuses, :students_as_array_by_status
38
+
39
+
40
+
41
+ # CSV CODE
42
+ ##########
43
+
44
+ # Queries by status to get a list of students details of a given status
45
+ # and converts the result to a CSV string with headers (based on keys sent)
46
+ #
47
+ # ==== Attributes
48
+ # * +status+ - hash to convert to an array
49
+ # * +flatten_keys+ - an array of keys to bring to the top level
50
+ # (with this key prepened) -- default (blank does nothing)
51
+ # * +reject_keys+ - an array of keys to remove from the data -- default (blank does nothing)
52
+ # * +student_keys+ - [:id, :name] - include student record keys
53
+ # * +guardian_info+ - include guardian record info {count: 2, keys: [:id, :name]}
54
+ # * +payment_info+ - include payment info {count: 2, order: :newest, keys: [:date, :amount]}
55
+ # * guardian & payment info options:
56
+ # count: 2 -- how many parent or payment records to return)
57
+ # keys: [:id, :date] -- an array of keys of data to return
58
+ # order: :newest -- the order to return payments :newest (most recent first - default) or :oldest
59
+ def students_as_csv_by_status( status,
60
+ flatten_keys=[], reject_keys=[],
61
+ student_keys=[],
62
+ guardian_info={}, payment_info={})
63
+ #
64
+ check = check_details_keys_validity(flatten_keys, reject_keys)
65
+ return check unless check.nil? # or check[:error].nil?
66
+ # check = check_header_keys_validity(student_keys, guardian_info, payment_info)
67
+ # return check unless check.nil?
68
+ #
69
+ students_array = students_as_array_by_status( status,
70
+ flatten_keys, reject_keys,
71
+ student_keys, guardian_info, payment_info )
72
+ #
73
+ return students_array if students_array.is_a? Hash
74
+ #
75
+ student_csv_txt = students_array_to_csv( students_array )
76
+ end
77
+ alias_method :students_as_csv_by_statuses, :students_as_csv_by_status
78
+
79
+ # Given an array convert to CSV string
80
+ #
81
+ # ==== Attributes
82
+ # +array+ - expects a hash of students_details (should be flattened to use custom fields)
83
+ def students_array_to_csv(array)
84
+ return "" if array.nil? or array.empty?
85
+ # https://stackoverflow.com/questions/4822422/output-array-to-csv-in-ruby
86
+ csv_string = CSV.generate do |csv|
87
+ array.each do |row|
88
+ csv << row
89
+ end
90
+ end
91
+ return csv_string
92
+ end
93
+
94
+
95
+ # XLSX CODE
96
+ ###########
97
+
98
+
99
+ # Queries by status to get a list of students details of a given status
100
+ # and converts the result to a XLSX Object (Axlsx::Package) with headers
101
+ # (based on keys sent)
102
+ #
103
+ # ==== Attributes
104
+ # * +status+ - hash to convert to an array
105
+ # * +flatten_keys+ - an array of keys to bring to the top level
106
+ # (with this key prepened) -- default (blank does nothing)
107
+ # * +reject_keys+ - an array of keys to remove from the data -- default (blank does nothing)
108
+ # * +student_keys+ - [:id, :name] - include student record keys
109
+ # * +guardian_info+ - include guardian record info {count: 2, keys: [:id, :name]}
110
+ # * +payment_info+ - include payment info {count: 2, order: :newest, keys: [:date, :amount]}
111
+ # * guardian & payment info options:
112
+ # count: 2 -- how many parent or payment records to return)
113
+ # keys: [:id, :date] -- an array of keys of data to return
114
+ # order: :newest -- the order to return payments :newest (most recent first - default) or :oldest
115
+ def students_as_xlsx_by_status( status,
116
+ flatten_keys=[], reject_keys=[],
117
+ student_keys=[],
118
+ guardian_info={}, payment_info={})
119
+ #
120
+ check = check_details_keys_validity(flatten_keys, reject_keys)
121
+ return check unless check.nil? # or check[:error].nil?
122
+ # check = check_header_keys_validity(student_keys, guardian_info, payment_info)
123
+ # return check unless check.nil?
124
+ #
125
+ students_array = students_as_array_by_status( status,
126
+ flatten_keys, reject_keys,
127
+ student_keys, guardian_info, payment_info )
128
+ #
129
+ return students_array if students_array.is_a? Hash
130
+ #
131
+ students_xlsx = students_array_to_xlsx( students_array )
132
+
133
+ # example how to save the xlsx object as a file
134
+ # students_xlsx.serialize("spec/data/xlsx/students_from_oa.xlsx")
135
+
136
+ return students_xlsx
137
+ end
138
+ alias_method :students_as_xlsx_by_statuses, :students_as_xlsx_by_status
139
+
140
+
141
+ # Given an array convert to XLSX Object (Axlsx::Package)
142
+ #
143
+ # ==== Attributes
144
+ # +array+ - expects a hash of students_details (should be flattened to use custom fields)
145
+ def students_array_to_xlsx(student_array)
146
+ xlsx_obj = Axlsx::Package.new do |p|
147
+ p.workbook.add_worksheet(:name => "Students from OpenApply") do |sheet|
148
+ student_array.each{ |r| sheet.add_row r }
149
+ end
150
+ # to save the xlsx object as a file
151
+ # p.serialize("spec/data/xlsx/students_from_oa.xlsx")
152
+ end
153
+ return xlsx_obj
154
+ end
155
+
156
+
157
+ # ARRAY CODE
158
+ ############
159
+
160
+ # Given an hash of students_details converts to an arrary
161
+ #
162
+ # ==== Attributes
163
+ # * +students+ - hash to convert to an array
164
+ # * +student_keys+ - [:id, :name] - include student record keys
165
+ # * +guardian_info+ - include guardian record info {count: 2, keys: [:id, :name]}
166
+ # * +payment_info+ - include payment info {count: 2, order: :newest, keys: [:date, :amount]}
167
+ # * guardian & payment info options:
168
+ # count: 2 -- how many parent or payment records to return)
169
+ # keys: [:id, :date] -- an array of keys of data to return
170
+ # order: :newest -- the order to return payments :newest (most recent first - default) or :oldest
171
+ def students_hash_to_array(students, student_keys=[], guardian_info={}, payment_info={})
172
+
173
+ check = check_header_keys_validity(student_keys, guardian_info, payment_info)
174
+ return check unless check.nil?
175
+
176
+ array = []
177
+ array << create_headers( student_keys, guardian_info, payment_info )
178
+ return array if students.nil? or students.empty?
179
+
180
+ students[:students].each do |student|
181
+ row = []
182
+
183
+ # next if student.nil? or student.empty? or
184
+ # student[:record].nil? or student[:record].empty?
185
+
186
+ kid_record = student[:record]
187
+ guardians = student[:guardians]
188
+ payments = student[:payments]
189
+
190
+ # inject student record info into the array
191
+ student_keys.each{ |key| row << kid_record[key] }
192
+
193
+ # inject guardian record info into the array
194
+ if process_key_info?(guardian_info)
195
+ count = info_count(guardian_info).to_i - 1
196
+ # loop through the correct number of parents
197
+ (0..count).each do |i|
198
+ # add info if parent record exists
199
+ guardian_info[:keys].each{ |key| row << guardians[i][key] } if guardians[i]
200
+ # add nils if there isn't a parent record
201
+ guardian_info[:keys].each{ |key| row << nil } unless guardians[i]
202
+ end
203
+ end
204
+
205
+ # inject guardian record info (most recent - last to oldest) into the array
206
+ if process_key_info?(payment_info)
207
+ if payment_info[:order].nil? or payment_info[:order].eql? :newest
208
+ # get the newest records first
209
+ count = info_count(payment_info).to_i
210
+ # loop through the correct number of parents
211
+ (1..count).each do |index|
212
+ i = index * -1
213
+ # puts "INDEX #{i}"
214
+ payment_info[:keys].each{ |key| row << payments[i][key] } if payments[i]
215
+ payment_info[:keys].each{ |key| row << nil } unless payments[i]
216
+ end
217
+ else
218
+ # start with the oldest records
219
+ count = info_count(payment_info).to_i - 1
220
+ # loop through the correct number of parents
221
+ (0..count).each do |i|
222
+ payment_info[:keys].each{ |key| row << payments[i][key] } if payments[i]
223
+ payment_info[:keys].each{ |key| row << nil } unless payments[i]
224
+ end
225
+ end
226
+ end
227
+ array << row
228
+ end
229
+ return array
230
+ end
231
+
232
+ # internal key to process given info or not
233
+ def process_key_info?(info)
234
+ return true unless info.nil? or info.empty? or
235
+ info[:keys].nil? or info[:keys].empty?
236
+ return false
237
+ end
238
+
239
+ # determine count - may extend later to self-discover max number of records
240
+ def info_count(info)
241
+ info[:count] || 1
242
+ end
243
+
244
+ # Given the parameters passed in create the create csv / arrary headers
245
+ #
246
+ # ==== Attributes
247
+ # * +students+ - hash to convert to an array
248
+ # * +student_keys+ - include student record keys
249
+ # * +guardian_info+ - include guardian record info {count: 2, keys: [:id, :name]}
250
+ # * +payment_info+ - include payment info {count: 2, order: :newest, keys: [:date, :amount]}
251
+ # * guardian & payment info options:
252
+ # count: 2 -- how many parent or payment records to return)
253
+ # keys: [:id, :date] -- an array of keys of data to return
254
+ # order: :newest -- the order to return payments :newest (most recent first - default) or :oldest
255
+ def create_headers( student_keys=[], guardian_info={}, payment_info={} )
256
+ headers = []
257
+ # figure out student headers
258
+ student_keys = [:id] if student_keys.nil? or student_keys.empty?
259
+ headers = student_keys.map{ |k| "student_" + k.to_s }
260
+ # figure out guardian headers
261
+ if process_key_info?(guardian_info)
262
+ guardian_count = info_count(guardian_info)
263
+ # add the correct headers
264
+ (1..guardian_count).each do |i|
265
+ headers += guardian_info[:keys].map{|k| "guardian#{i}_" + k.to_s }
266
+ end
267
+ end
268
+ # calculate payment headers
269
+ if process_key_info?(payment_info)
270
+ payment_count = info_count(payment_info)
271
+ # add the correct headers
272
+ (1..payment_count).each do |i|
273
+ headers += payment_info[:keys].map{|k| "payment#{i}_" + k.to_s }
274
+ end
275
+ end
276
+ return headers
277
+ end
278
+
279
+ # XFER CODE
280
+ ###########
281
+
282
+ # Send a string to convert to a file on a remote server
283
+ # setup using ssh keys - not sure how to test - use at own risk
284
+ #
285
+ # === Attributes
286
+ # * +data+ - object to be converted to a file on a remote system --
287
+ # object can be a CSV String, Axlsx::Package or File object to be transfered
288
+ # * +srv_hostname+ - fqdn or IP address of the remote host
289
+ # * +srv_hostname+ - username to access the remote host
290
+ # * +srv_path_file+ - full path and file name of the file on the remote host
291
+ # * +file_permissions+ - permissions to make the file on the remote host (default is: 0750)
292
+ def send_data_to_remote_server( data, srv_hostname, srv_username,
293
+ srv_path_file, file_permissions='0750')
294
+ # https://www.safaribooksonline.com/library/view/ruby-cookbook/0596523696/ch06s15.html
295
+ # convert the string to a stringio object (which can act as a file)
296
+
297
+ # just move the file via SCP
298
+ xfer = data if data.is_a? File
299
+ # convert string into a SteamIO - "FILE" like object
300
+ xfer = data if data.is_a? StringIO
301
+ # convert string into a SteamIO - "FILE" like object
302
+ xfer = StringIO.new( data ) if data.is_a? String
303
+ # convert Axlsx object into a SteamIO - "FILE" like object
304
+ xfer = data.to_stream() if data.is_a? Axlsx::Package
305
+
306
+ # be sure its a file type that can be sent
307
+ return "Unrecognized Object" unless known_transfer_object?(data)
308
+
309
+ # http://www.rubydoc.info/github/delano/net-scp/Net/SCP
310
+ # send the stringio object to the remote host via scp
311
+ Net::SCP.start(srv_hostname, srv_username) do |scp|
312
+ # asynchronous upload; call returns immediately
313
+ channel = scp.upload( xfer, srv_path_file )
314
+ channel.wait
315
+ end
316
+ # ensure file has desired permissions (via remote ssh command)
317
+ Net::SSH.start(srv_hostname, srv_username) do |ssh|
318
+ # Capture all stderr and stdout output from a remote process
319
+ output = ssh.exec!("chmod #{file_permissions} #{srv_path_file}")
320
+ end
321
+ end
322
+ alias_method :send_string_to_server_file, :send_data_to_remote_server
323
+
324
+ # Check that the data to transfer is of a known data type
325
+ #
326
+ # === Attributes
327
+ # * +data+ - is it an Axlsx::Package, Sting, StringIO or a File class?
328
+ def known_transfer_object?( data )
329
+ return true if data.is_a? String or data.is_a? Axlsx::Package or
330
+ data.is_a? File or data.is_a? StringIO
331
+ return false
332
+ end
333
+
334
+ # Check header info before processing
335
+ #
336
+ # === Attributes
337
+ # * +student_keys+ - that this is an arrary of symbols
338
+ # * +guardian_info+ - that this is a hash with keys: using symbols
339
+ # * +payment_info+ - that this is a hash with keys: using symbols
340
+ def check_header_keys_validity(student_keys, guardian_info, payment_info)
341
+ # prepare keys for testing
342
+ student_keys ||= []
343
+ #
344
+ #
345
+ guardian_info ||= {}
346
+ return {error: "invalid guardian_info - use hash"} unless guardian_info.is_a? Hash
347
+ guardian_keys = guardian_info[:keys] #unless guardian_keys[:keys].nil?
348
+ guardian_keys ||= []
349
+ #
350
+ payment_info ||= {}
351
+ return {error: "invalid payment_info - use hash"} unless payment_info.is_a? Hash
352
+ payment_keys = payment_info[:keys] #unless payment_keys[:keys].nil?
353
+ payment_keys ||= []
354
+
355
+ # be sure keys are in an array
356
+ return {error: "invalid student_keys - need array"} unless student_keys.is_a? Array
357
+ return {error: "invalid guardian_keys - need array"} unless guardian_keys.is_a? Array
358
+ return {error: "invalid payment_keys - need array"} unless payment_keys.is_a? Array
359
+
360
+ # test if any key values are non-symbols (remain after removing symbols)
361
+ return {error: "invalid student_keys - use symbols"} if student_keys.reject{|k| k.is_a? Symbol}.count > 0
362
+ return {error: "invalid guardian_keys - use symbols"} if guardian_keys.reject{|k| k.is_a? Symbol}.count > 0
363
+ return {error: "invalid payment_keys - use symbols"} if payment_keys.reject{|k| k.is_a? Symbol}.count > 0
364
+
365
+ # check that if guardian info is given - it also has keys
366
+ return {error: "invalid guardian_keys - keys missing"} if not guardian_info.empty? and guardian_info[:keys].nil?
367
+ return {error: "invalid payment_keys - keys missing"} if not payment_info.empty? and payment_info[:keys].nil?
368
+
369
+ end
370
+
371
+ end