Created
September 4, 2011 19:33
-
-
Save txus/1193383 to your computer and use it in GitHub Desktop.
ShitDB - YAML-backed document-oriented database in pure ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
my_db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'minitest/spec' | |
require 'minitest/autorun' | |
require 'yaml' | |
class DB | |
def initialize(name) | |
@name = File.join(File.dirname(__FILE__), name) | |
end | |
def collection(name) | |
Collection.new(self, name) | |
end | |
def file | |
@file ||= File.exist?(@name) ? YAML.load(File.open(@name)) : {} | |
end | |
def persist | |
File.open(@name, 'w') do |f| | |
f.write YAML.dump(@file) | |
end | |
end | |
end | |
class Collection | |
attr_reader :db | |
def initialize(db, name) | |
@db = db | |
@name = name | |
@db.file[@name] ||= [] | |
@db.file["_#{@name}_last_id"] ||= 0 | |
end | |
def persist | |
@db.persist | |
end | |
def get(id) | |
@db.file[@name].detect do |record| | |
record[:id] == id | |
end | |
end | |
def put(doc) | |
new_id = @db.file["_#{@name}_last_id"] + 1 | |
@db.file[@name] << doc.update(:id => new_id) | |
@db.file["_#{@name}_last_id"] = new_id | |
end | |
def all | |
@db.file[@name] | |
end | |
def where(attrs) | |
@db.file[@name].select do |record| | |
attrs.map do |attr| | |
record[attr.first] == attr.last | |
end.all?{|n| n == true} | |
end | |
end | |
end | |
require 'fileutils' | |
describe 'acceptance tests' do | |
before do | |
FileUtils.rm('my_db') if File.exist?('my_db') | |
@users = DB.new('my_db').collection('users') | |
end | |
describe 'storage' do | |
it 'saves records in memory' do | |
@users.put(:name => 'James') | |
@users.put(:name => 'John', :age => 30) | |
users = @users.all.map { |record| record[:name] } | |
assert_equal 2, users.length | |
assert_includes users, 'James' | |
assert_includes users, 'John' | |
end | |
it 'does not save them to disk' do | |
@users.put(:name => 'James') | |
@users.put(:name => 'John', :age => 30) | |
persisted = DB.new('my_db').collection('users').all | |
assert_equal 0, persisted.length | |
end | |
it 'persists them when told so' do | |
@users.put(:name => 'James') | |
@users.put(:name => 'John', :age => 30) | |
@users.persist | |
users = DB.new('my_db').collection('users').all.map { |record| record[:name] } | |
assert_equal 2, users.length | |
assert_includes users, 'James' | |
assert_includes users, 'John' | |
end | |
end | |
describe 'querying' do | |
before do | |
@users.put(:name => 'James') | |
@users.put(:name => 'John', :age => 30) | |
@users.put(:name => 'Charles', :age => 30) | |
end | |
it 'performs simple queries with one condition inefficiently' do | |
result = @users.where(:age => 30).map { |record| record[:name] } | |
assert_equal 2, result.length | |
assert_includes result, 'John' | |
assert_includes result, 'Charles' | |
end | |
it 'performs simple queries with multiple conditions inefficiently' do | |
result = @users.where(:name => 'Charles', :age => 30).map { |record| record[:name]} | |
assert_equal 1, result.length | |
assert_equal 'Charles', result.first | |
end | |
it 'retrieves records by id' do | |
james = @users.get(1) | |
john = @users.get(2) | |
charles = @users.get(3) | |
assert_equal 'James', james[:name] | |
assert_equal 'John', john[:name] | |
assert_equal 'Charles', charles[:name] | |
end | |
end | |
describe 'consistency' do | |
it 'assigns autoincremental ids' do | |
@users.put(:name => 'James') | |
@users.put(:name => 'John') | |
ids = @users.all.map { |record| record[:id] }.compact | |
assert_equal 2, ids.length | |
refute_equal ids.first, ids.last | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment