data_fabric 1.1.0 → 1.2.0
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/CHANGELOG +4 -0
- data/Manifest +73 -0
- data/README.rdoc +1 -1
- data/Rakefile +34 -8
- data/data_fabric.gemspec +7 -7
- data/example/app/models/figment.rb +1 -1
- data/example/db/development.sqlite3 +0 -0
- data/example/db/s0_development.sqlite3 +0 -0
- data/example/db/s0_test.sqlite3 +0 -0
- data/example/db/s1_development.sqlite3 +0 -0
- data/example/db/s1_test.sqlite3 +0 -0
- data/example/db/test.sqlite3 +0 -0
- data/example/vendor/plugins/data_fabric/init.rb +1 -0
- data/example/vendor/plugins/data_fabric/lib/data_fabric.rb +106 -0
- data/example/vendor/plugins/data_fabric/lib/data_fabric/ar20.rb +135 -0
- data/example/vendor/plugins/data_fabric/lib/data_fabric/ar22.rb +172 -0
- data/example/vendor/plugins/data_fabric/lib/data_fabric/version.rb +5 -0
- data/example22/Rakefile +58 -0
- data/example22/app/controllers/accounts_controller.rb +22 -0
- data/example22/app/controllers/application.rb +39 -0
- data/example22/app/controllers/figments_controller.rb +8 -0
- data/example22/app/helpers/application_helper.rb +3 -0
- data/example22/app/models/account.rb +3 -0
- data/example22/app/models/figment.rb +4 -0
- data/example22/app/views/accounts/index.html.erb +47 -0
- data/example22/app/views/layouts/application.html.erb +8 -0
- data/example22/config/boot.rb +109 -0
- data/example22/config/database.yml +21 -0
- data/example22/config/environment.rb +76 -0
- data/example22/config/environments/development.rb +17 -0
- data/example22/config/environments/production.rb +24 -0
- data/example22/config/environments/test.rb +22 -0
- data/example22/config/initializers/inflections.rb +10 -0
- data/example22/config/initializers/mime_types.rb +5 -0
- data/example22/config/initializers/new_rails_defaults.rb +17 -0
- data/example22/config/locales/en.yml +5 -0
- data/example22/config/routes.rb +46 -0
- data/example22/db/migrate/20080702154628_create_accounts.rb +14 -0
- data/example22/db/migrate/20080702154820_create_figments.rb +14 -0
- data/example22/public/404.html +30 -0
- data/example22/public/422.html +30 -0
- data/example22/public/500.html +33 -0
- data/example22/public/dispatch.cgi +10 -0
- data/example22/public/dispatch.fcgi +24 -0
- data/example22/public/dispatch.rb +10 -0
- data/example22/public/favicon.ico +0 -0
- data/example22/public/images/rails.png +0 -0
- data/example22/public/index.html +274 -0
- data/example22/public/javascripts/application.js +2 -0
- data/example22/public/javascripts/controls.js +963 -0
- data/example22/public/javascripts/dragdrop.js +973 -0
- data/example22/public/javascripts/effects.js +1128 -0
- data/example22/public/javascripts/prototype.js +4320 -0
- data/example22/public/robots.txt +5 -0
- data/example22/script/about +4 -0
- data/example22/script/console +3 -0
- data/example22/script/dbconsole +3 -0
- data/example22/script/destroy +3 -0
- data/example22/script/generate +3 -0
- data/example22/script/performance/benchmarker +3 -0
- data/example22/script/performance/profiler +3 -0
- data/example22/script/performance/request +3 -0
- data/example22/script/plugin +3 -0
- data/example22/script/process/inspector +3 -0
- data/example22/script/process/reaper +3 -0
- data/example22/script/process/spawner +3 -0
- data/example22/script/runner +3 -0
- data/example22/script/server +3 -0
- data/example22/test/fixtures/accounts.yml +7 -0
- data/example22/test/functional/accounts_controller_test.rb +12 -0
- data/example22/test/integration/account_figments_test.rb +97 -0
- data/example22/test/performance/browsing_test.rb +9 -0
- data/example22/test/test_helper.rb +38 -0
- data/lib/data_fabric.rb +7 -132
- data/lib/data_fabric/ar20.rb +133 -0
- data/lib/data_fabric/ar22.rb +172 -0
- data/lib/data_fabric/version.rb +1 -1
- data/test/connection_test.rb +6 -2
- data/test/database_test.rb +26 -2
- data/test/test_helper.rb +34 -28
- data/test/thread_test.rb +19 -11
- data/test/vr_austin_master.db +0 -0
- data/test/vr_austin_slave.db +0 -0
- data/test/vr_dallas_master.db +0 -0
- data/test/vr_dallas_slave.db +0 -0
- metadata +79 -5
@@ -0,0 +1,172 @@
|
|
1
|
+
module DataFabric
|
2
|
+
module Extensions
|
3
|
+
def self.included(model)
|
4
|
+
# Wire up ActiveRecord::Base
|
5
|
+
model.extend ClassMethods
|
6
|
+
ConnectionProxy.shard_pools = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
# Class methods injected into ActiveRecord::Base
|
10
|
+
module ClassMethods
|
11
|
+
def data_fabric(options)
|
12
|
+
DataFabric.log { "Creating data_fabric proxy for class #{name}" }
|
13
|
+
@proxy = DataFabric::ConnectionProxy.new(self, options)
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def connection
|
17
|
+
@proxy
|
18
|
+
end
|
19
|
+
|
20
|
+
def connected?
|
21
|
+
@proxy.connected?
|
22
|
+
end
|
23
|
+
|
24
|
+
def remove_connection(klass)
|
25
|
+
DataFabric.log(Logger::ERROR) { "remove_connection not implemented by data_fabric" }
|
26
|
+
end
|
27
|
+
|
28
|
+
def connection_pool
|
29
|
+
raise "dynamic connection switching means you cannot get direct access to a pool"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class ConnectionProxy
|
37
|
+
cattr_accessor :shard_pools
|
38
|
+
|
39
|
+
def initialize(model_class, options)
|
40
|
+
@model_class = model_class
|
41
|
+
@replicated = options[:replicated]
|
42
|
+
@shard_group = options[:shard_by]
|
43
|
+
@prefix = options[:prefix]
|
44
|
+
set_role('slave') if @replicated
|
45
|
+
|
46
|
+
@model_class.send :include, ActiveRecordConnectionMethods if @replicated
|
47
|
+
end
|
48
|
+
|
49
|
+
delegate :insert, :update, :delete, :create_table, :rename_table, :drop_table, :add_column, :remove_column,
|
50
|
+
:change_column, :change_column_default, :rename_column, :add_index, :remove_index, :initialize_schema_information,
|
51
|
+
:dump_schema_information, :execute, :execute_ignore_duplicate, :to => :master
|
52
|
+
|
53
|
+
delegate :insert_many, :to => :master # ar-extensions bulk insert support
|
54
|
+
|
55
|
+
def transaction(start_db_transaction = true, &block)
|
56
|
+
# Transaction is not re-entrant in SQLite 3 so we
|
57
|
+
# need to track if we've already started an XA to avoid
|
58
|
+
# calling it twice.
|
59
|
+
return yield if in_transaction?
|
60
|
+
|
61
|
+
with_master do
|
62
|
+
connection.transaction(start_db_transaction, &block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def method_missing(method, *args, &block)
|
67
|
+
DataFabric.log(Logger::DEBUG) { "Calling #{method} on #{connection}" }
|
68
|
+
connection.send(method, *args, &block)
|
69
|
+
end
|
70
|
+
|
71
|
+
def connection_name
|
72
|
+
connection_name_builder.join('_')
|
73
|
+
end
|
74
|
+
|
75
|
+
def with_master
|
76
|
+
# Allow nesting of with_master.
|
77
|
+
old_role = current_role
|
78
|
+
set_role('master')
|
79
|
+
yield
|
80
|
+
ensure
|
81
|
+
set_role(old_role)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def in_transaction?
|
87
|
+
current_role == 'master'
|
88
|
+
end
|
89
|
+
|
90
|
+
def current_pool
|
91
|
+
name = connection_name
|
92
|
+
self.class.shard_pools[name] ||= begin
|
93
|
+
config = ActiveRecord::Base.configurations[name]
|
94
|
+
raise ArgumentError, "Unknown database config: #{name}, have #{ActiveRecord::Base.configurations.inspect}" unless config
|
95
|
+
ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec_for(config))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def spec_for(config)
|
100
|
+
# XXX This looks pretty fragile. Will break if AR changes how it initializes connections and adapters.
|
101
|
+
config = config.symbolize_keys
|
102
|
+
adapter_method = "#{config[:adapter]}_connection"
|
103
|
+
initialize_adapter(config[:adapter])
|
104
|
+
ActiveRecord::Base::ConnectionSpecification.new(config, adapter_method)
|
105
|
+
end
|
106
|
+
|
107
|
+
def initialize_adapter(adapter)
|
108
|
+
begin
|
109
|
+
require 'rubygems'
|
110
|
+
gem "activerecord-#{adapter}-adapter"
|
111
|
+
require "active_record/connection_adapters/#{adapter}_adapter"
|
112
|
+
rescue LoadError
|
113
|
+
begin
|
114
|
+
require "active_record/connection_adapters/#{adapter}_adapter"
|
115
|
+
rescue LoadError
|
116
|
+
raise "Please install the #{adapter} adapter: `gem install activerecord-#{adapter}-adapter` (#{$!})"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def connection_name_builder
|
122
|
+
@connection_name_builder ||= begin
|
123
|
+
clauses = []
|
124
|
+
clauses << @prefix if @prefix
|
125
|
+
clauses << @shard_group if @shard_group
|
126
|
+
clauses << StringProxy.new { DataFabric.active_shard(@shard_group) } if @shard_group
|
127
|
+
clauses << RAILS_ENV
|
128
|
+
clauses << StringProxy.new { current_role } if @replicated
|
129
|
+
clauses
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def connection
|
134
|
+
current_pool.connection
|
135
|
+
end
|
136
|
+
|
137
|
+
def active?
|
138
|
+
DataFabric.shard_active_for?(@shard_group)
|
139
|
+
end
|
140
|
+
|
141
|
+
def set_role(role)
|
142
|
+
Thread.current[:data_fabric_role] = role
|
143
|
+
end
|
144
|
+
|
145
|
+
def current_role
|
146
|
+
Thread.current[:data_fabric_role]
|
147
|
+
end
|
148
|
+
|
149
|
+
def master
|
150
|
+
with_master { return connection }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
module ActiveRecordConnectionMethods
|
155
|
+
def self.included(base)
|
156
|
+
base.alias_method_chain :reload, :master
|
157
|
+
end
|
158
|
+
|
159
|
+
def reload_with_master(*args, &block)
|
160
|
+
connection.with_master { reload_without_master }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class StringProxy
|
165
|
+
def initialize(&block)
|
166
|
+
@proc = block
|
167
|
+
end
|
168
|
+
def to_s
|
169
|
+
@proc.call
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
data/example22/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
|
+
|
4
|
+
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
|
5
|
+
|
6
|
+
require 'rake'
|
7
|
+
require 'rake/testtask'
|
8
|
+
require 'rake/rdoctask'
|
9
|
+
|
10
|
+
require 'tasks/rails'
|
11
|
+
|
12
|
+
require 'fileutils'
|
13
|
+
include FileUtils::Verbose
|
14
|
+
|
15
|
+
namespace :db do
|
16
|
+
task :migrate do
|
17
|
+
require 'erb'
|
18
|
+
require 'logger'
|
19
|
+
require 'active_record'
|
20
|
+
reference = YAML::load(ERB.new(IO.read("config/database.yml")).result)
|
21
|
+
env = RAILS_ENV = ENV['RAILS_ENV'] || 'development'
|
22
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
23
|
+
ActiveRecord::Base.logger.level = Logger::WARN
|
24
|
+
ActiveRecord::Base.configurations = reference.dup
|
25
|
+
old_config = reference[env]
|
26
|
+
reference.each_key do |name|
|
27
|
+
next unless name.include? env
|
28
|
+
next if name.include? 'slave' # Replicated databases should not be touched directly
|
29
|
+
|
30
|
+
puts "Migrating #{name}"
|
31
|
+
ActiveRecord::Base.clear_active_connections!
|
32
|
+
ActiveRecord::Base.configurations[env] = reference[name]
|
33
|
+
ActiveRecord::Base.establish_connection RAILS_ENV
|
34
|
+
ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
35
|
+
ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
namespace :app do
|
41
|
+
task :prepare => [:clean, :copy_plugin, :migrate]
|
42
|
+
|
43
|
+
task :copy_plugin do
|
44
|
+
mkdir_p 'vendor/plugins/data_fabric'
|
45
|
+
cp_r '../lib', 'vendor/plugins/data_fabric'
|
46
|
+
cp '../init.rb', 'vendor/plugins/data_fabric'
|
47
|
+
end
|
48
|
+
|
49
|
+
task :clean do
|
50
|
+
rm_rf 'vendor/plugins/data_fabric'
|
51
|
+
rm_f 'db/*.sqlite3'
|
52
|
+
end
|
53
|
+
|
54
|
+
task :migrate do
|
55
|
+
sh "rake db:migrate"
|
56
|
+
sh "rake RAILS_ENV=test db:migrate"
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class AccountsController < ApplicationController
|
2
|
+
layout 'application'
|
3
|
+
|
4
|
+
def index
|
5
|
+
@accounts = Account.find(:all)
|
6
|
+
end
|
7
|
+
|
8
|
+
def choose
|
9
|
+
@account = Account.find(params[:id])
|
10
|
+
if @account
|
11
|
+
session[:account_id] = @account.id
|
12
|
+
flash[:notice] = "Selected account: #{@account.name}"
|
13
|
+
end
|
14
|
+
redirect_to '/'
|
15
|
+
end
|
16
|
+
|
17
|
+
def create
|
18
|
+
Account.create!(params[:acct])
|
19
|
+
flash[:notice] = "Account created successfully"
|
20
|
+
redirect_to '/'
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Filters added to this controller apply to all controllers in the application.
|
2
|
+
# Likewise, all the methods added will be available for all controllers.
|
3
|
+
|
4
|
+
class ApplicationController < ActionController::Base
|
5
|
+
helper :all # include all helpers, all the time
|
6
|
+
|
7
|
+
# See ActionController::RequestForgeryProtection for details
|
8
|
+
# Uncomment the :secret if you're not using the cookie session store
|
9
|
+
protect_from_forgery # :secret => '44f8cf8a0491c23ae99c031a900123cc'
|
10
|
+
|
11
|
+
# See ActionController::Base for details
|
12
|
+
# Uncomment this to filter the contents of submitted sensitive data parameters
|
13
|
+
# from your application log (in this case, all fields with names like "password").
|
14
|
+
# filter_parameter_logging :password
|
15
|
+
|
16
|
+
before_filter :find_account
|
17
|
+
around_filter :select_shard
|
18
|
+
|
19
|
+
private
|
20
|
+
def find_account
|
21
|
+
aid = session[:account_id]
|
22
|
+
if aid && aid.to_i != 0
|
23
|
+
begin
|
24
|
+
@account = Account.find(Integer(aid))
|
25
|
+
rescue ActiveRecord::RecordNotFound => e
|
26
|
+
RAILS_DEFAULT_LOGGER.warn "No such account #{aid}, skipping..."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
session[:account_id] = nil unless @account
|
30
|
+
end
|
31
|
+
|
32
|
+
def select_shard(&block)
|
33
|
+
if @account
|
34
|
+
DataFabric.activate_shard(:shard => @account.shard, &block)
|
35
|
+
else
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<hr/>
|
2
|
+
<h2>Accounts</h2>
|
3
|
+
<table>
|
4
|
+
<thead>
|
5
|
+
<tr><th>ID</th><th>Name</th><th>Shard</th><th> </th></tr>
|
6
|
+
</thead>
|
7
|
+
<tbody>
|
8
|
+
<% @accounts.each do |account| %>
|
9
|
+
<tr>
|
10
|
+
<td><%= account.id %></td>
|
11
|
+
<td><%= account.name %></td>
|
12
|
+
<td><%= account.shard %></td>
|
13
|
+
<td><%= link_to 'Choose', choose_account_path(account) %></td>
|
14
|
+
</tr>
|
15
|
+
<% end %>
|
16
|
+
</tbody>
|
17
|
+
</table>
|
18
|
+
<hr/>
|
19
|
+
<h2>New Account</h2>
|
20
|
+
<p>
|
21
|
+
<% form_for :acct, :url => accounts_path do |f| %>
|
22
|
+
Name : <%= f.text_field :name %><br/>
|
23
|
+
Shard: <%= select 'acct', 'shard', [[0,0],[1,1]] %><br/>
|
24
|
+
<%= submit_tag 'Save' %>
|
25
|
+
<% end %>
|
26
|
+
</p>
|
27
|
+
<hr/>
|
28
|
+
<% if @account %>
|
29
|
+
<h2>Current Account: <%= @account.name %></h2>
|
30
|
+
<table>
|
31
|
+
<thead>
|
32
|
+
<tr><th>ID</th><th>Account</th><th>Value</th></tr>
|
33
|
+
</thead>
|
34
|
+
<tbody>
|
35
|
+
<% @account.figments.each do |fig| %>
|
36
|
+
<tr>
|
37
|
+
<td><%= fig.id %></td>
|
38
|
+
<td><%= fig.account.name %></td>
|
39
|
+
<td><%= fig.value %></td>
|
40
|
+
</tr>
|
41
|
+
<% end %>
|
42
|
+
</tbody>
|
43
|
+
</table>
|
44
|
+
Add Fig: <% form_for :figment, :url => figments_path do |f| %><%= f.text_field :value %><%= submit_tag 'Save' %><% end %>
|
45
|
+
<% else %>
|
46
|
+
<em>No account selected.</em>
|
47
|
+
<% end %>
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# Don't change this file!
|
2
|
+
# Configure your app in config/environment.rb and config/environments/*.rb
|
3
|
+
|
4
|
+
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
5
|
+
|
6
|
+
module Rails
|
7
|
+
class << self
|
8
|
+
def boot!
|
9
|
+
unless booted?
|
10
|
+
preinitialize
|
11
|
+
pick_boot.run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def booted?
|
16
|
+
defined? Rails::Initializer
|
17
|
+
end
|
18
|
+
|
19
|
+
def pick_boot
|
20
|
+
(vendor_rails? ? VendorBoot : GemBoot).new
|
21
|
+
end
|
22
|
+
|
23
|
+
def vendor_rails?
|
24
|
+
File.exist?("#{RAILS_ROOT}/vendor/rails")
|
25
|
+
end
|
26
|
+
|
27
|
+
def preinitialize
|
28
|
+
load(preinitializer_path) if File.exist?(preinitializer_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def preinitializer_path
|
32
|
+
"#{RAILS_ROOT}/config/preinitializer.rb"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Boot
|
37
|
+
def run
|
38
|
+
load_initializer
|
39
|
+
Rails::Initializer.run(:set_load_path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class VendorBoot < Boot
|
44
|
+
def load_initializer
|
45
|
+
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
|
46
|
+
Rails::Initializer.run(:install_gem_spec_stubs)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class GemBoot < Boot
|
51
|
+
def load_initializer
|
52
|
+
self.class.load_rubygems
|
53
|
+
load_rails_gem
|
54
|
+
require 'initializer'
|
55
|
+
end
|
56
|
+
|
57
|
+
def load_rails_gem
|
58
|
+
if version = self.class.gem_version
|
59
|
+
gem 'rails', version
|
60
|
+
else
|
61
|
+
gem 'rails'
|
62
|
+
end
|
63
|
+
rescue Gem::LoadError => load_error
|
64
|
+
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
|
68
|
+
class << self
|
69
|
+
def rubygems_version
|
70
|
+
Gem::RubyGemsVersion rescue nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def gem_version
|
74
|
+
if defined? RAILS_GEM_VERSION
|
75
|
+
RAILS_GEM_VERSION
|
76
|
+
elsif ENV.include?('RAILS_GEM_VERSION')
|
77
|
+
ENV['RAILS_GEM_VERSION']
|
78
|
+
else
|
79
|
+
parse_gem_version(read_environment_rb)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def load_rubygems
|
84
|
+
require 'rubygems'
|
85
|
+
min_version = '1.3.1'
|
86
|
+
unless rubygems_version >= min_version
|
87
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
88
|
+
exit 1
|
89
|
+
end
|
90
|
+
|
91
|
+
rescue LoadError
|
92
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
93
|
+
exit 1
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_gem_version(text)
|
97
|
+
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
def read_environment_rb
|
102
|
+
File.read("#{RAILS_ROOT}/config/environment.rb")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# All that for this:
|
109
|
+
Rails.boot!
|