Commit cb6a3d5a by John Doe

working on db parsing

parent 75bcc2b7
--color --color
--require spec_helper --require spec_helper
--format documentation
\ No newline at end of file
...@@ -16,7 +16,8 @@ class DbAdapter ...@@ -16,7 +16,8 @@ class DbAdapter
start_time: entry[2] || 0, start_time: entry[2] || 0,
end_time: entry[3] || 0, end_time: entry[3] || 0,
total_rows: entry[4], total_rows: entry[4],
total_time: entry[5] } total_time: entry[5],
metadata: {} }
end end
end end
end end
...@@ -2,56 +2,95 @@ ...@@ -2,56 +2,95 @@
# Handles construction of database objects # Handles construction of database objects
class DbBuilder class DbBuilder
def initialize(db:, db_service:) def initialize(db:)
@db = db @db = db
@db_service = db_service
end end
def update_db def update_db(schema:)
entries = @db_service.schema # split path into chunks
#split path into chunks entries = schema.map do |entry|
entries.map! do |entry|
entry[:chunks] = entry[:path][1..-1].split('/').reverse entry[:chunks] = entry[:path][1..-1].split('/').reverse
entry entry
end end
if(@db.root_folder == nil) # create the root folder if it doesn't exist
@db.root_folder=__build_folder(entries: entries, default_name: 'root') @db.root_folder ||= DbFolder.create(name: 'root', path: '/')
end @root_folder = @db.root_folder
#group entries by first chunk # add the folder entries
#find or create an entry with the single chunk 'info' __parse_folder_entries(parent: nil, entries: entries)
#if the group contains one entry that is *not* 'info', make it a file
#if the group contains multiple entries, make it a folder
#..recursive
end end
protected protected
def __build_folder(entries:, default_name:) def __parse_folder_entries(parent:, entries:, default_name: '')
folder = DbFolder.new(name: default_name) # find the info stream entry if it exists
entry_groups = Hash.new() info = __read_info_entry(entries) || { name: default_name }
entries.map do |entry| # generate the folder path
__add_to_group(entry_groups, entry[:chunks].pop, entry) path = __build_path(entries)
end # create or update the folder
entry_groups.each do |name, entry_group| folder = __build_folder(parent: parent, path: path, info: info)
if(entry_group.length==1) # group the folder entries
folder.db_files << __build_file(entry: entry_group, default_name: name) groups = __group_entries(entries)
elsif(entry_group.length > 1) # convert the entries into subfolders and files
folder.subfolders << __build_folder(entries: entry_group, default_name: name) groups.each do |name, entry_group|
if entry_group.length == 1
folder.db_files << __build_file(folder: folder, entry: entry_group[0],
default_name: name)
elsif entry_group.length > 1
folder.subfolders << __parse_folder_entries(parent: folder,
entries: entry_group,
default_name: name)
end end
end end
folder folder
end end
def __read_info_entry(entries)
if entries[0][:chunks] == ['info']
info_entry = entries.slice!(0)
info_entry[:metadata]
end
end
def __build_folder(parent:, path:, info:)
return @root_folder if parent.nil?
folder = parent.subfolders.find_by_path(path)
folder ||= DbFolder.new(parent: parent, path: path)
folder.update_attributes(info)
folder.save!
folder
end
def __build_file(folder:, entry:, default_name:)
file = folder.db_files.find_by_path(entry[:path])
file ||= DbFile.new(name: default_name)
file.save!
file
end
def __build_path(entries)
# all entries agree on a common path
# up to the point where they still have
# chunks. Get this common path by popping
# the chunks off the first entry's path
parts = entries[0][:path].split('/')
parts.pop(entries[0][:chunks].length)
parts.join('/') # stitch parts together to form a path
end
def __group_entries(entries)
entry_groups = {}
entries.map do |entry|
__add_to_group(entry_groups, entry[:chunks].pop, entry)
end
entry_groups
end
def __add_to_group(entry_groups, group_name, entry) def __add_to_group(entry_groups, group_name, entry)
if entry_groups[group_name] == nil entry_groups[group_name] ||= []
entry_groups[group_name] = [entry] if entry[:chunks] == ['info'] # put the info stream in front
entry_groups[group_name].prepend(entry)
else else
entry_groups[group_name].push(entry) entry_groups[group_name].append(entry)
end end
end end
def __build_file(entry:, default_name:)
file = DbFile.new(name: default_name)
end
end end
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# and one or more DbFolders as subfolders # and one or more DbFolders as subfolders
class DbFolder < ActiveRecord::Base class DbFolder < ActiveRecord::Base
belongs_to :parent, class_name: 'DbFolder' belongs_to :parent, class_name: 'DbFolder'
has_many :subfolders, class_name: 'DbFolder', foreign_key: 'db_folder_id' has_many :subfolders, class_name: 'DbFolder', foreign_key: 'parent_id'
has_many :db_files has_many :db_files
def insert_file(file:) def insert_file(file:)
......
...@@ -8,7 +8,7 @@ describe DbAdapter do ...@@ -8,7 +8,7 @@ describe DbAdapter do
adapter = DbAdapter.new(db.url) adapter = DbAdapter.new(db.url)
adapter.schema.map do |entry| adapter.schema.map do |entry|
expect(entry).to include(:path, :type, :start_time, expect(entry).to include(:path, :type, :start_time,
:end_time, :total_rows, :total_time) :end_time, :total_rows, :total_time, :metadata)
end end
end end
end end
# frozen_string_literal: true # frozen_string_literal: true
require 'rails_helper' require 'rails_helper'
helper = DbSchemaHelper.new
# schema data # a simple schema that could be returned
def entry(path, type = 'uint8_1') # from DbAdapater.schema
{ path: path, type: type, simple_db = [ # folder1
start_time: 0, end_time: 0, helper.entry('/folder1/file1_1'), # `- file1_1
total_rows: 0, total_time: 0 helper.entry('/folder1/file1_2'), # - file1_2
} helper.entry('/folder2/file2_1'), # folder2
end helper.entry('/folder2/file2_2'), # '- file2_1
] # `- file2_2
simple_db = [
entry('/folder1/info'),
entry('/folder1/file1'),
entry('/folder1/file2'),
entry('/empty_folder/info')
]
describe DbBuilder do describe DbBuilder do
describe '*update_db*' do
describe 'update_db' do before(:all) do
let(:db) { Db.new } @db = Db.new
it 'initializes an empty database' do @db_builder = DbBuilder.new(db: @db)
db_service = instance_double('DbService', schema: simple_db) end
db_builder = DbBuilder.new(db: db, db_service: db_service) describe 'given the simple_db schema' do
db_builder.update_db before(:all) do
expect(db.root_folder.name).to eq('root') @db_builder.update_db(schema: simple_db)
@root = @db.root_folder
end
it 'builds a root folder' do
expect(@root.name).to eq('root')
expect(@root.subfolders.count).to eq(2)
expect(@root.db_files.count).to eq(0)
end
it 'builds sub-folder1' do
folder1 = @root.subfolders[0]
expect(folder1.name).to eq('folder1')
expect(folder1.db_files.count).to eq(2)
expect(folder1.db_files[0].name).to eq('file1_1')
expect(folder1.db_files[1].name).to eq('file1_2')
end
it 'builds sub-folder2' do
folder2 = @root.subfolders[1]
expect(folder2.name).to eq('folder2')
expect(folder2.db_files.count).to eq(2)
expect(folder2.db_files[0].name).to eq('file2_1')
expect(folder2.db_files[1].name).to eq('file2_2')
end
end
describe 'given simple_db schema with folder info streams' do
before(:all) do
simple_db << helper.entry('/folder1/info', metadata: { name: 'first' })
simple_db << helper.entry('/folder2/info', metadata: { name: 'second' })
@db_builder.update_db(schema: simple_db)
end
it 'uses the name info'
end end
end end
end end
# frozen_string_literal: true
# Helpers to produce database schemas that
# are usually returned by DbAdapter.schema
class DbSchemaHelper
# schema data
def entry(path, type: 'uint8_1', metadata: {})
{ path: path, type: type,
start_time: 0, end_time: 0,
total_rows: 0, total_time: 0,
metadata: metadata
}
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment