50 lines
1.1 KiB
Ruby
50 lines
1.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'csv'
|
|
require 'fileutils'
|
|
require 'time'
|
|
|
|
module BBS
|
|
class Store
|
|
def initialize(path:, headers:)
|
|
@path = path
|
|
@headers = headers
|
|
@mutex = Mutex.new
|
|
end
|
|
|
|
def upsert(session_id:, **fields)
|
|
@mutex.synchronize do
|
|
ensure_file!
|
|
rows = CSV.read(@path, headers: true)
|
|
row = rows.find { |r| r['session_id'] == session_id }
|
|
|
|
if row
|
|
fields.each { |k, v| row[k.to_s] = v }
|
|
else
|
|
values = @headers.map do |h|
|
|
case h
|
|
when 'session_id' then session_id
|
|
when 'timestamp' then Time.now.utc.iso8601
|
|
else fields[h.to_sym]
|
|
end
|
|
end
|
|
rows << CSV::Row.new(@headers, values)
|
|
end
|
|
|
|
CSV.open(@path, 'w') do |csv|
|
|
csv << @headers
|
|
rows.each { |r| csv << r.fields }
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def ensure_file!
|
|
FileUtils.mkdir_p(File.dirname(@path))
|
|
return if File.exist?(@path)
|
|
CSV.open(@path, 'w') { |csv| csv << @headers }
|
|
end
|
|
end
|
|
end
|