wraithdb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +28 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/lib/gems/activerecord-import.rb +16 -0
- data/lib/gems/db-charmer.rb +23 -0
- data/lib/rails/3.0/active_record/base.rb +39 -0
- data/lib/rails/3.0/arel/table.rb +27 -0
- data/lib/rails/3.2/active_record/model_schema.rb +27 -0
- data/lib/wraithdb/adapter.rb +43 -0
- data/lib/wraithdb/column.rb +16 -0
- data/lib/wraithdb/schema.rb +39 -0
- data/lib/wraithdb/version.rb +3 -0
- data/lib/wraithdb.rb +13 -0
- data/wraithdb.gemspec +18 -0
- metadata +85 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
©2011 Airbnb, Inc.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
Redistributions of source code must retain the above copyright notice,
|
8
|
+
this list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
Names of the contributors to this software may not be used to endorse or
|
15
|
+
promote products derived from this software without specific prior written
|
16
|
+
permission.
|
17
|
+
|
18
|
+
This software is provided by the contributors "as is" and any express or
|
19
|
+
implied warranties, including, but not limited to, the implied warranties
|
20
|
+
of merchantability and fitness for a particular purpose are disclaimed. In
|
21
|
+
no event shall the contributors be liable for any direct, indirect,
|
22
|
+
incidental, special, exemplary, or consequential damages (including, but not
|
23
|
+
limited to, procurement of substitute goods or services; loss of use, data,
|
24
|
+
or profits; or business interruption) however caused and on any theory of
|
25
|
+
liability, whether in contract, strict liability, or tort (including
|
26
|
+
negligence or otherwise) arising in any way out of the use of this
|
27
|
+
software, even if advised of the possibility of such damage.
|
28
|
+
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Wraithdb
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'wraithdb'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install wraithdb
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
class << self
|
4
|
+
def establish_connection_with_activerecord_import(*args)
|
5
|
+
establish_connection_without_activerecord_import(*args)
|
6
|
+
begin
|
7
|
+
ActiveSupport.run_load_hooks(:active_record_connection_established, connection)
|
8
|
+
rescue StandardError => e
|
9
|
+
# ActiveImport will not work but this shouldn't be an issue as it's only used in Rake tasks.
|
10
|
+
# If the DB is down we won't be importing anything in a rake task anyhow.
|
11
|
+
end
|
12
|
+
end
|
13
|
+
alias establish_connection establish_connection_with_activerecord_import
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
class << self
|
4
|
+
# This clobbers the DB Charmer wrapping of relation and does the same thing except
|
5
|
+
# it leaves connection resolution to runtime rather than assigning an instance variable
|
6
|
+
def relation_with_db_charmer(*args, &block)
|
7
|
+
relation_without_db_charmer(*args, &block).tap do |rel|
|
8
|
+
begin
|
9
|
+
rel.db_charmer_connection = @connection
|
10
|
+
rescue StandardError => e
|
11
|
+
base = self
|
12
|
+
rel.define_singleton_method(:db_charmer_connection) do
|
13
|
+
base.connection
|
14
|
+
end
|
15
|
+
end
|
16
|
+
rel.db_charmer_enable_slaves = self.db_charmer_slaves.any?
|
17
|
+
rel.db_charmer_connection_is_forced = !db_charmer_top_level_connection?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
alias relation relation_with_db_charmer
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
class << self
|
4
|
+
#If we do variable binding inside of where clauses on scopes it needs to work without
|
5
|
+
#an actual connection. The implementation provided mirrors the Mysql2Adapter
|
6
|
+
def replace_bind_variables_with_wraithdb(statement, values)
|
7
|
+
begin
|
8
|
+
replace_bind_variables_without_wraithdb
|
9
|
+
rescue StandardError => e
|
10
|
+
raise e if e.kind_of? PreparedStatementInvalid
|
11
|
+
bound = values.dup
|
12
|
+
statement.gsub('?') { quote_bound_value(bound.shift, WraithDB::Schema.connection) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
alias_method_chain :replace_bind_variables, :wraithdb
|
16
|
+
|
17
|
+
def table_exists_with_wraithdb_columns?
|
18
|
+
begin
|
19
|
+
table_exists_without_wraithdb_columns?
|
20
|
+
rescue StandardError => e
|
21
|
+
WraithDB::Schema.tables.has_key?(table_name.to_s)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
alias_method_chain :table_exists?, :wraithdb_columns
|
25
|
+
|
26
|
+
def columns_with_wraithdb_columns
|
27
|
+
begin
|
28
|
+
columns_without_wraithdb_columns
|
29
|
+
rescue StandardError => e
|
30
|
+
columns = WraithDB::Schema.tables[table_name.to_s].columns
|
31
|
+
return columns.map {|column|
|
32
|
+
WraithDB::Column.new(column)
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
alias_method_chain :columns, :wraithdb_columns
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Arel
|
2
|
+
class Table
|
3
|
+
def columns_with_wraithdb
|
4
|
+
begin
|
5
|
+
columns_without_wraithdb
|
6
|
+
rescue StandardError => e
|
7
|
+
attributes_for WraithDB::Schema.tables[@name].columns
|
8
|
+
end
|
9
|
+
end
|
10
|
+
alias_method_chain :columns, :wraithdb
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def table_cache_with_wraithdb(engine)
|
14
|
+
begin
|
15
|
+
table_cache_without_wraithdb(engine)
|
16
|
+
rescue StandardError => e
|
17
|
+
tables = {}
|
18
|
+
WraithDB::Schema.tables.keys.each do |table_name|
|
19
|
+
tables[table_name] = true
|
20
|
+
end
|
21
|
+
tables
|
22
|
+
end
|
23
|
+
end
|
24
|
+
alias_method_chain :table_cache, :wraithdb
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ModelSchema
|
3
|
+
module ClassMethods
|
4
|
+
def table_exists_with_wraithdb_columns?
|
5
|
+
begin
|
6
|
+
table_exists_without_wraithdb_columns?
|
7
|
+
rescue StandardError => e
|
8
|
+
WraithDB.schema.tables.has_key?(table_name.to_s)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
alias_method_chain :table_exists?, :wraithdb_columns
|
12
|
+
|
13
|
+
def columns_with_wraithdb_columns
|
14
|
+
begin
|
15
|
+
columns_without_wraithdb_columns
|
16
|
+
rescue StandardError => e
|
17
|
+
columns = WraithDB.schema.tables[table_name.to_s].columns
|
18
|
+
return columns.map {|column|
|
19
|
+
WraithDB::Column.new(column)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
alias_method_chain :columns, :wraithdb_columns
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module WraithDB
|
2
|
+
class Adapter < ActiveRecord::ConnectionAdapters::AbstractAdapter
|
3
|
+
attr_reader :tables
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
super(nil)
|
7
|
+
@active = true
|
8
|
+
@tables = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def quote(value, column = nil)
|
12
|
+
if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary)
|
13
|
+
s = column.class.string_to_binary(value).unpack("H*")[0]
|
14
|
+
"x'#{s}'"
|
15
|
+
elsif value.kind_of?(BigDecimal)
|
16
|
+
value.to_s("F")
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def adapter_name
|
23
|
+
'WraithDB'
|
24
|
+
end
|
25
|
+
|
26
|
+
def support_migrations?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_table(table_name, options = {})
|
31
|
+
table_definition = ActiveRecord::ConnectionAdapters::TableDefinition.new(self)
|
32
|
+
table_definition.primary_key(options[:primary_key] || ActiveRecord::Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
|
33
|
+
|
34
|
+
yield table_definition if block_given?
|
35
|
+
|
36
|
+
@tables[table_name.to_s] = table_definition
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_index(*args)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module WraithDB
|
2
|
+
class Column < ActiveRecord::ConnectionAdapters::Column
|
3
|
+
def initialize(column_definition)
|
4
|
+
@name = column_definition.name
|
5
|
+
@sql_type = nil
|
6
|
+
@null = column_definition.null
|
7
|
+
@limit = column_definition.limit
|
8
|
+
@precision = column_definition.precision
|
9
|
+
@scale = column_definition.scale
|
10
|
+
@type = (column_definition.type == :primary_key) ? :integer : column_definition.type
|
11
|
+
@default = column_definition.default
|
12
|
+
@primary = column_definition.type == :primary_key
|
13
|
+
@coder = nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module WraithDB
|
2
|
+
class Schema < ActiveRecord::Schema
|
3
|
+
SCHEMA_REGEX = /^ActiveRecord::Schema.define\(:version => \d+\) do/
|
4
|
+
END_REGEX = /^end\s*\z/
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def write(*args)
|
8
|
+
# normally this would be noisy like a migration, this makes it quiet
|
9
|
+
end
|
10
|
+
|
11
|
+
def connection
|
12
|
+
load
|
13
|
+
@connection ||= WraithDB::Adapter.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def tables
|
17
|
+
connection.tables
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def load
|
24
|
+
return if @loaded
|
25
|
+
@loaded = true
|
26
|
+
file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb"
|
27
|
+
source = File.read(file)
|
28
|
+
if (source =~ SCHEMA_REGEX && source =~ END_REGEX)
|
29
|
+
source.sub!(SCHEMA_REGEX, "")
|
30
|
+
source.sub!(END_REGEX, "")
|
31
|
+
else
|
32
|
+
raise StandardError.new("Invalid format for #{file}.")
|
33
|
+
end
|
34
|
+
|
35
|
+
instance_eval(source)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/wraithdb.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'active_record/connection_adapters/abstract/schema_definitions'
|
2
|
+
require "wraithdb/version"
|
3
|
+
require 'wraithdb/schema'
|
4
|
+
require 'wraithdb/column'
|
5
|
+
require 'wraithdb/adapter'
|
6
|
+
|
7
|
+
dir_path = File.expand_path('..', __FILE__)
|
8
|
+
|
9
|
+
Dir["#{dir_path}/rails/#{Rails.version[0..2]}/**/*.rb"].each {|file| require file}
|
10
|
+
Dir["#{dir_path}/gems/**/*.rb"].each { |file|
|
11
|
+
gem_name = file.gsub(/.*\/|\..*/, '')
|
12
|
+
require file if Gem.loaded_specs.has_key?(gem_name)
|
13
|
+
}
|
data/wraithdb.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/wraithdb/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Nathan Baxter"]
|
6
|
+
gem.email = ["nathan.baxter@airbnb.com"]
|
7
|
+
gem.description = %q{WraithDB uses schema.rb as a template to initialize ActiveRecord classes when databases are offline. It does this with minimal overhead, leaving the normal connection object untouched and only interacting with the columns and tables interfaces.}
|
8
|
+
gem.summary = %q{Allows Rails to boot in the absence of a working database.}
|
9
|
+
gem.homepage = "https://github.com/airbnb/wraithdb"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "wraithdb"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Wraithdb::VERSION
|
17
|
+
gem.add_runtime_dependency 'activerecord', '>= 3.0', '<= 3.2'
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wraithdb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nathan Baxter
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-26 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
- - <=
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '3.2'
|
25
|
+
type: :runtime
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
33
|
+
- - <=
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '3.2'
|
36
|
+
description: WraithDB uses schema.rb as a template to initialize ActiveRecord classes
|
37
|
+
when databases are offline. It does this with minimal overhead, leaving the normal
|
38
|
+
connection object untouched and only interacting with the columns and tables interfaces.
|
39
|
+
email:
|
40
|
+
- nathan.baxter@airbnb.com
|
41
|
+
executables: []
|
42
|
+
extensions: []
|
43
|
+
extra_rdoc_files: []
|
44
|
+
files:
|
45
|
+
- .gitignore
|
46
|
+
- Gemfile
|
47
|
+
- LICENSE
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- lib/gems/activerecord-import.rb
|
51
|
+
- lib/gems/db-charmer.rb
|
52
|
+
- lib/rails/3.0/active_record/base.rb
|
53
|
+
- lib/rails/3.0/arel/table.rb
|
54
|
+
- lib/rails/3.2/active_record/model_schema.rb
|
55
|
+
- lib/wraithdb.rb
|
56
|
+
- lib/wraithdb/adapter.rb
|
57
|
+
- lib/wraithdb/column.rb
|
58
|
+
- lib/wraithdb/schema.rb
|
59
|
+
- lib/wraithdb/version.rb
|
60
|
+
- wraithdb.gemspec
|
61
|
+
homepage: https://github.com/airbnb/wraithdb
|
62
|
+
licenses: []
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.8.24
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: Allows Rails to boot in the absence of a working database.
|
85
|
+
test_files: []
|