TalentBox / sequel-rails

A gem for using Sequel with Rails 5.x, 6.x, 7.x, 8.x
http://talentbox.github.io/sequel-rails/
MIT License
326 stars 81 forks source link

rails db:create doesn't work #158

Open unrooty opened 6 years ago

unrooty commented 6 years ago

I have such error running rails db:create. Can anybody help?

rails aborted!
Sequel::Error: No database associated with Sequel::Model: have you called Sequel.connect or Sequel::Model.db= ?
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/sequel-5.5.0/lib/sequel/model/base.rb:353:in `db'
/home/vladislav/taxi_project_api/config/initializers/sequel.rb:3:in `<main>'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/bootsnap-1.1.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `load'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/bootsnap-1.1.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `load'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/dependencies.rb:277:in `block in load'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/dependencies.rb:249:in `load_dependency'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/dependencies.rb:277:in `load'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/engine.rb:657:in `block in load_config_initializer'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/notifications.rb:170:in `instrument'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/engine.rb:656:in `load_config_initializer'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/engine.rb:614:in `block (2 levels) in <class:Engine>'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/engine.rb:613:in `each'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/engine.rb:613:in `block in <class:Engine>'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/initializable.rb:32:in `instance_exec'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/initializable.rb:32:in `run'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/initializable.rb:61:in `block in run_initializers'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/initializable.rb:50:in `each'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/initializable.rb:50:in `tsort_each_child'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/initializable.rb:60:in `run_initializers'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/application.rb:360:in `initialize!'
/home/vladislav/taxi_project_api/config/environment.rb:5:in `<main>'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/bootsnap-1.1.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:17:in `require'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/bootsnap-1.1.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:17:in `require'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/dependencies.rb:283:in `block in require'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/dependencies.rb:249:in `load_dependency'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/dependencies.rb:283:in `require'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/application.rb:336:in `require_environment!'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/application.rb:519:in `block in run_tasks_blocks'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/command.rb:48:in `invoke'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/railties-5.2.0.rc1/lib/rails/commands.rb:18:in `<main>'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/bootsnap-1.1.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:17:in `require'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/bootsnap-1.1.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:17:in `require'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/dependencies.rb:283:in `block in require'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/dependencies.rb:249:in `load_dependency'
/home/vladislav/.rvm/gems/ruby-2.5.0/gems/activesupport-5.2.0.rc1/lib/active_support/dependencies.rb:283:in `require'
bin/rails:4:in `<main>'
Tasks: TOP => db:create => environment
(See full trace by running task with --trace)
SkylerLipthay commented 6 years ago

I am guessing on line 3 of initializers/sequel.rb you have something like DB = Sequel::Model.db. If you comment this line out temporarily then rails db:create will work.

I just encountered this problem. It's weird because rails db:drop or rails db:migrate or rails c do not have a problem with that initializer. It's only rails db:create that does not have Sequel::Model.db loaded by the time of the initializer.

Jesterovskiy commented 6 years ago

Same issue in my project. I use this workaround:

begin
  DB = Sequel::Model.db
  DB.extension :pg_array, :pg_json, :pg_enum
rescue Sequel::Error
end
bgentry commented 6 years ago

This happens for me on a brand new Rails project which has no references to Sequel other than the gem 'sequel-rails' bit in the Gemfile.

This is the culprit: it's called in database.rake as part of any task. Ideally these rake tasks would work even if we couldn't preconnect to the specific database.

unrooty commented 6 years ago

I found a solution that works in my case.

The error exists because of full environment initialization during the rake task invocation. So when I try to create the database, it loads my initializers, where I have Sequel customization. And even if I place it under the ActiveSupport lazy load hook (on_load(:sequel) do ), trailblazer-loader gem will do force loading of models, which will execute the hook and once again I will catch an error and no database will be created.

So possible solutions is to: 1) don't load all the env for rake task (currently I use this one), 2) to rescue Sequel database errors and force execute createdb commands.

My rake task looks like this:

Rake::Task['db:create'].clear
namespace :db do
  desc 'Create the database defined in config/database.yml for the current Rails.env'
  task :create do
    database_config = {
      Rails.env => Rails.application.config_for('database')
    }

    ::SequelRails::Configuration.for(Rails.root, database_config)

    unless SequelRails::Storage.create_environment(Rails.env)
      abort "Could not create database for #{Rails.env}."
    end
  end
end
bgentry commented 6 years ago

Digging a little deeper into this, the problem is that the code that decides whether to connect to the database is dependent on ARGV, which appears to always be []. When I placed a debugger there, I saw:

[1] pry(#<SequelRails::Railtie>)> database_connection_required?(app)
=> true
[2] pry(#<SequelRails::Railtie>)> ARGV
=> []

This is true even if I run spring:stop before running the rake task to ensure that no preloader is getting in the way.

bgentry commented 6 years ago

In railtie.rb, this initializer is the source of this problem:

    initializer 'sequel.connect' do |app|
      ::SequelRails.setup(::Rails.env) if database_connection_required?(app)
    end

If I change that conditional to if Rails.env.production? the rake tasks all seem to work, and rake -T no longer requires a database connection.

Is there a reason it needs to run at all, or run outside of production?

bgentry commented 6 years ago

So it does seem that we need to call Sequel.connect at some point before actually using the database. The fact that this is done in an initializer and is always run, even for rake tasks, causes a bunch of problems. But I'm not sure there's a better place where this could be done (like at a later stage of Rails initialization or something). I'm not aware of any other hooks in the boot process we could use. Anybody have an idea for how to solve this?

This also causes some issues when attempting to solve #159, because I have to figure out a way to disconnect Sequel before the parallel test processes are forked. Currently the parallel testing support doesn't have any hooks that can be called pre-fork, but one may need to be added to make this compatible with Sequel / sequel-rails.

ptadros commented 6 years ago

So I had the same problem and spent couple of days to figure out the problem and the solution. So basically, Sequel read database configuration directly from config/database.yml. In this case you don't need the initializer at all. What makes sequel to skip usingdatabase.yml` and asks you for a database connection if you explicitly skipped database connection in the application startup using the following option

config.sequel.skip_connect = true

If you removed this option and have the correct database config in database.yml, rake db:create will work correctly. Per their docs, they fixed an issue with db:create rake task in version 1.0.1 https://github.com/TalentBox/sequel-rails/blob/master/History.md I'm using Rails 5, sequel-rails (1.0.1) I hope this can help anyone faces the same issue.

bgentry commented 6 years ago

If you create a brand new rails app w/ sequel-rails (and no initializer at all) the issue is still present. So it happens even without skip_connect.

gencer commented 6 years ago

Have the same problem in test environment. I cannot pass tests due to db:create fails. No matter of skip_connect true or false

unrooty commented 6 years ago

@gencer, try to use my solution, it should work.

gencer commented 6 years ago

@unrooty, I just applied your solution. However there is one problem. My application tries to execute an initializer from /initializers/doorkeeper.rb

Let me illustrate with log:

Creating DB  <= This is where your solution start to work. I put this message there.
--
rake aborted!
Sequel::Error: No database associated with Sequel::Model: have you called Sequel.connect or Sequel::Model.db= ?
/var/lib/build-agent/builds/build-1/bp/endpoint/config/initializers/doorkeeper.rb:3:in `<main>'
/var/lib/build-agent/builds/build-1/bp/endpoint/config/environment.rb:5:in `<main>'
/var/lib/build-agent/.rbenv/versions/2.5.1/bin/bundle:23:in `load'
/var/lib/build-agent/.rbenv/versions/2.5.1/bin/bundle:23:in `<main>'
Tasks: TOP => db:drop => environment
(See full trace by running task with --trace)

Do you know how can I make sure this initializers should not executed or at least not complain about my database?

Doorkeeper is using orm :sequel at line 3

nbulaj commented 6 years ago

hi @gencer . @unrooty works with database without loading application env. So it looks strange that you command loads initializers.

Also it is possible that Doorkeeper (or Doorkeeper-Sequel) directly loads Sequel, so it triggers the error (but as far as I remember doorkeeper-sequel uses lazy loading of Sequel gem). You can try to bypass this problem by adding a "top-level" initializer like GitLab does (config/initializers/001_sequel.rb) where you will disable table presence validations. By "top-level" initializer I mean the file that will be loaded first.

gencer commented 6 years ago

@nbulaj, I tried something like in initializers/001_sequel.rb;

if Rails.env.test?
    ::Sequel::Model.require_valid_table = false
end

or just ::Sequel::Model.require_valid_table = false. However, doorkeeper.rb#3 complains about database not table. I still get Sequel::Error: No database associated with Sequel::Model: have you called Sequel.connect or Sequel::Model.db= ? error.

Do you know any method so that doorkeeper-sequel does not complain about my database exists or not.?

Interestingly, db:drop and other tasks just works.

ptadros commented 6 years ago

@gencer Have you tried to remove config.sequel.skip_connect = true config completely, remove the initializer and try to run the rake task again?

gencer commented 6 years ago

@engpeter2010 yes, That was the first thing I tried.

ptadros commented 6 years ago

@gencer and which sequel-rails version do you use?

gencer commented 6 years ago

@engpeter2010 v1.0.1 (latest available at the moment.)

They claim this version has included fixes about db:create. However, one of my initializers (doorkeeper.rb#3 using as orm: sequel) is complaining about my database.

Maybe internally true, however, this is my case.

ptadros commented 6 years ago

@gencer: I think it might be something related to Doorkeeper-sequel gem as I don't use Doorkeeper but sequel-rails. It is a strange issue. I spent hours to know the trick with sequel-rails as the doc is not clear. Hopefully, you will find a solution soon.

On Wed, 18 Jul 2018 19:35 Gencer W. Genç, notifications@github.com wrote:

@engpeter2010 https://github.com/engpeter2010 v1.0.1 (latest available at the moment.)

They claim this version has included fixes about db:create. However, one of my initializers (doorkeeper.rb#3 using as orm: sequel) is complaining about my database.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/TalentBox/sequel-rails/issues/158#issuecomment-406013555, or mute the thread https://github.com/notifications/unsubscribe-auth/ACAbisWSnrHfbRM9eXEF8AFU5HeIm9L0ks5uH3HogaJpZM4SYA-h .

kgilpin commented 5 years ago

Try enabling extensions only after the DB connection is successfully established, per https://github.com/TalentBox/sequel-rails#enabling-plugins. For example:

Rails.application.config.sequel.after_connect = proc do
  Sequel::Model.db.extension :pg_json
end
MorneL commented 5 years ago

Is there any update on this yet?

I am unable to run rake db:create if I have an existing Sequel:model

I'm also getting this error Sequel::Error: No database associated with Sequel::Model: have you called Sequel.connect or Sequel::Model.db= ? but it doesn't make sense that I have called Sequel.connect as there is no db to connect to.

JonathanTron commented 5 years ago

Hi @MorneL, what version of Rails are you using?

If you're using Rails >= 5.0, then can you try: rails db:create (instead of rake db:create)?

I don't have any issue on a fresh Rails 5.2 app using sequel-rails if I invoke the command via rails (eg: rake -T -> rails -T, etc).

gencer commented 5 years ago

@JonathanTron. On fresh installed Rails, there is no problem. I believe @MorneL is using some kind of extension that rely on Sequel (e.g.: sequel-devise or doorkeeper-sequel etc ...). In this case, this error shows up.