在独立的ActiveRecord应用程序中连接数据库时遇到问题

时间:2019-02-10 19:45:10

标签: ruby activerecord

我正在编写一个gem,它是一个命令行工具,并试图弄清楚如何让ActiveRecord在其中运行以管理数据库。

我从一个有效的ActiveRecord项目开始(Flatiron新手训练营课程),分别构建了一个gem(bundle gem gemname),然后手工将gem的所有文件结构复制并改编到AR项目中。请注意,我没有使用Rails或任何其他可能包装ActiveRecord的框架。

我已尽力进行了设置,但似乎无法弄清楚最后一英里:我无法对数据库进行任何操作。

$ rake db:create
rake aborted!
ActiveRecord::AdapterNotSpecified: 'development' database is not configured. Available: []

$ rake db:migrate
rake aborted!
ActiveRecord::ConnectionNotEstablished: No connection pool with 'primary' found.

以下是该项目中的一些相关内容:

# FILE STRUCTURE

LearnManager
| .travis.yml
| Gemfile.lock
| Rakefile
| LICENSE.md
| Gemfile
| CONTRIBUTING.md
| .rspec
| .gitignore
| .git
| app
| | models
| | | unit.rb
| | | topic.rb
| | | lesson.rb
| bin
| | setup
| | console
| config
| | db
| | | schema.rb
| | | learnmanager-development.db
| | migrate
| | | 20190210190844_create_lessons
| lib
| | LearnManager.rb
| | LearnManager
| | | version.rb
| | support
| | | db_registry.rb
| | | connection_adapter.rb
| spec
| | spec_helper.rb
| LearnManager.gemspec
# config/environment.rb
require 'bundler/setup'
Bundler.require

require 'rake'
require 'active_record'
require 'yaml/store'
require 'ostruct'
require 'date'

DBNAME = "learnmanager"

Dir[File.join(File.dirname(__FILE__), "../app/models", "*.rb")].each {|f| require f}
Dir[File.join(File.dirname(__FILE__), "../lib/support", "*.rb")].each {|f| require f}

DBRegistry[ENV["ACTIVE_RECORD_ENV"]].connect!
DB = ActiveRecord::Base.connection

if ENV["ACTIVE_RECORD_ENV"] == "test"
  ActiveRecord::Migration.verbose = false
end
# db/migrate/20190210190844_create_lessons
class CreateLessons < ActiveRecord::Migration[5.2]
  def change
    create_table :lessons do |t|
      t.string :title
      t.belongs_to :unit, index: true
    end
  end
end
# app/models/lesson.rb
class Lesson < ActiveRecord::Base
  belongs_to :unit
end  
# db/schema.rb
ActiveRecord::Schema.define(version: 0) do
  create_table :topics, force: true do |t|
    t.string :name
  end

  create_table :units, force: true do |t|
    t.string :name
    t.belongs_to :topic, index: true
  end

create_table :lessons, force: true do |t|
    t.string :name
    t.belongs_to :unit, index: true
  end
end
# lib/support/connection_adapter.rb
class ConnectionAdapter
  attr_reader :adapter, :database

  def initialize(database, adapter="sqlite3")
    @adapter = adapter
    @database = database
  end

  def connect!
    ActiveRecord::Base.establish_connection(
      :adapter => self.adapter,
      :database => self.database
    )
  end
end
# lib/support/db_registry.rb
require_relative "./connection_adapter.rb"

DBRegistry ||= OpenStruct.new(test: ConnectionAdapter.new("db/#{DBNAME}-test.db"), 
  development: ConnectionAdapter.new("db/#{DBNAME}-development.db"), 
  production: ConnectionAdapter.new("db/#{DBNAME}-production.db")
  )
# Rakefile
require 'bundler/setup'
Bundler.require
require 'active_record'
require 'sinatra/activerecord/rake'
require 'pry'

task :environment do
  ENV["ACTIVE_RECORD_ENV"] ||= "development"
  require_relative './config/environment'
end

include ActiveRecord::Tasks
DatabaseTasks.db_dir = 'db'
DatabaseTasks.migrations_paths = 'db/migrate'
seed_loader = Class.new do
  def load_seed
    load "#{ActiveRecord::Tasks::DatabaseTasks.db_dir}/seeds.rb"
  end
end
DatabaseTasks.seed_loader = seed_loader.new
load 'active_record/railties/databases.rake'

task :console => :environment do
  Pry.start
end

# --------- FROM GEM BUILD --------- 
require "bundler/gem_tasks"
require "rspec/core/rake_task"

RSpec::Core::RakeTask.new(:spec)
# LearnManager.gemspec (excerpts)

lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "LearnManager/version"

Gem::Specification.new do |spec|
  spec.add_development_dependency "bundler", "~> 1.16"
  spec.add_development_dependency "rake", "~> 10.0"
  spec.add_development_dependency "rspec", "~> 3.0"

  spec.add_development_dependency "pry"
  spec.add_development_dependency "pry-byebug"
  spec.add_development_dependency "pry-rescue"

  spec.add_dependency "activerecord"
  spec.add_dependency "sqlite3", "~> 1.3.6"
  spec.add_dependency "database_cleaner"
  spec.add_dependency "sinatra-activerecord"  
end

有人知道我如何才能使它真正起作用吗?

1 个答案:

答案 0 :(得分:1)

我也这样做,但是我不使用耙子,我只使用纯红宝石。这是我项目中的两种方法,我在Rails之外使用Active Record。

基本上,我连接到数据库,检查表是否存在,如果不存在,则加载架构文件。加载架构后,我将使用常规ActiveRecord方法填充数据库并执行查询。我不需要进行迁移,所以我没有尝试过

class MyDb
  attr_reader :file_name
  def initialize(file_name)
    @file_name = file_name
  end

  def connect()
    @connection = ActiveRecord::Base.establish_connection(
      adapter: "sqlite3",
      database: filename,
    )
    create_tables unless tables_exists?
  end

  def tables_exists?
    ActiveRecord::Base.connection.tables.size > 0
  end

  def create_tables()
    puts "database is empty...\ncreating tables"
    path_to_current_file = File.expand_path(File.dirname(__FILE__))
    load("#{path_to_current_file}/ar_support/schema.rb")
  end
end

然后从顶级红宝石脚本中执行类似的操作。

my_db = MyDb.new("mydb.sqlite3")
my_db.connect

这是我也使用的一个示例schema.rb文件。

ActiveRecord::Schema.define(version: 20180430230151) do

  create_table "chips", force: :cascade do |t|
    t.string "name"
  end

  create_table "macros", force: :cascade do |t|
    t.string "name"
    t.integer "chip_id"
    t.index ["chip_id"], name: "index_macros_on_chip_id"
  end

  create_table "measurements", force: :cascade do |t|
    t.string "name"
    t.float "value"
    t.string "group_name"
    t.string "plot"
    t.boolean "test_result"
    t.string "test_expression"
    t.integer "run_id"
    t.index ["run_id"], name: "index_measurements_on_run_id"
  end

  create_table "runs", force: :cascade do |t|
    t.string "source_dir"
    t.string "source_file"
    t.integer "macro_id"
    t.string "corner_name"
    t.string "sim_type"
    t.string "netlist_type"
    t.index ["macro_id"], name: "index_runs_on_macro_id"
  end

  create_table "tags", force: :cascade do |t|
    t.string "name"
    t.integer "run_id"
    t.string "value"
    t.index ["run_id"], name: "index_tags_on_run_id"
  end

end

开始使用数据库。 (您还需要定义模型)

chip = Chip.find_or_create_by(name: e.chip)
macro = chip.macros.find_or_create_by(name: e.macro)