From 73bbb6d851361787bef784151e8185994e688ace Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 7 Mar 2019 08:59:45 +0100 Subject: [PATCH] application loading for rake tasks when no db exists Since rails 5, the whole of the application is loaded (including all initializers and models) when a rake task is to be executed. In case no database exists, e.g. when issuing a db:create, this runs into errors in case calls to ActiveRecord methods require the existence of a database. Using the null-db gem, we can mimick the existence of a db in such cases. Rails seems to reset the database connection to the one defined in the config/database.yml by itself. --- Gemfile | 3 + Gemfile.lock | 3 + config/initializers/05-null_db_fallback.rb | 36 ++++++++++++ lib/open_project/null_db_fallback.rb | 68 ++++++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 config/initializers/05-null_db_fallback.rb create mode 100644 lib/open_project/null_db_fallback.rb diff --git a/Gemfile b/Gemfile index e342cab14ce..5ec0f99859b 100644 --- a/Gemfile +++ b/Gemfile @@ -288,6 +288,9 @@ platforms :mri, :mingw, :x64_mingw do group :postgres do gem 'pg', '~> 1.1.0' end + + # Support application loading when no database exists yet. + gem 'activerecord-nulldb-adapter', '~> 0.3.9' end group :opf_plugins do diff --git a/Gemfile.lock b/Gemfile.lock index 184c18dc638..1e284d3a1b9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -257,6 +257,8 @@ GEM arel (>= 9.0) activerecord-import (0.28.1) activerecord (>= 3.2) + activerecord-nulldb-adapter (0.3.9) + activerecord (>= 2.0.0) activerecord-session_store (1.1.1) actionpack (>= 4.0) activerecord (>= 4.0) @@ -895,6 +897,7 @@ DEPENDENCIES actionpack-xml_parser (~> 2.0.0) activemodel-serializers-xml (~> 1.0.1) activerecord-import (~> 0.28.1) + activerecord-nulldb-adapter (~> 0.3.9) activerecord-session_store (~> 1.1.0) acts_as_list (~> 0.9.9) acts_as_tree (~> 2.8.0) diff --git a/config/initializers/05-null_db_fallback.rb b/config/initializers/05-null_db_fallback.rb new file mode 100644 index 00000000000..db0119e05db --- /dev/null +++ b/config/initializers/05-null_db_fallback.rb @@ -0,0 +1,36 @@ +#-- encoding: UTF-8 + +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +# Since Rails 5, rake commands like db:create load the whole application. +# As initializers and other parts of the boot sequence rely on calls accessing +# the DB, the null db gem is used to fake the existence of a database in cases where +# the db has not been created yet. + +OpenProject::NullDbFallback.fallback diff --git a/lib/open_project/null_db_fallback.rb b/lib/open_project/null_db_fallback.rb new file mode 100644 index 00000000000..f03edbbb614 --- /dev/null +++ b/lib/open_project/null_db_fallback.rb @@ -0,0 +1,68 @@ +#-- encoding: UTF-8 + +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +module OpenProject + module NullDbFallback + class << self + def fallback + ActiveRecord::Base.connection + rescue ActiveRecord::NoDatabaseError + applied! + ActiveRecord::Base.establish_connection adapter: :nulldb + end + + def reset + return unless applied? + + ActiveRecord::Base.establish_connection(database_config) + end + + private + + attr_accessor :applied + + def applied! + self.applied = true + end + + def unapplied! + self.applied = false + end + + def applied? + !!applied + end + + def database_config + YAML.load_file(File.join(Rails.root, "config", "database.yml"))[Rails.env] + end + end + end +end