wraithdb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|