Проблема с подключением к базе данных в автономном приложении ActiveRecord - PullRequest
0 голосов
/ 10 февраля 2019

Я пишу гем, который является инструментом командной строки, и пытаюсь выяснить, как заставить ActiveRecord работать в нем для управления базой данных.

Я начал с рабочего проекта ActiveRecord (загрузка Flatironлагерный урок), отдельно построил гем (bundle gem gemname), скопировал и адаптировал всю файловую структуру драгоценного камня в проект AR вручную.Обратите внимание, что я не использую Rails или другие фреймворки, которые могли бы иначе обернуть ActiveRecord.

Я настроил его как мог, но не могу понять последнюю милю: я могу 't сделать что-нибудь с базой данных.

$ 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 голосов
/ 11 февраля 2019

Я тоже так делаю, но я не использую грабли, я просто использую чистый рубин.Вот несколько методов из моего проекта, в которых я использую активную запись вне рельсов.

В основном я подключаюсь к базе данных, проверяю, существуют ли таблицы, и если нет, загружаю файл схемы.После загрузки схемы я просто использую обычные методы 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

Тогда изнутри скрипта Ruby верхнего уровня вы можете сделать что-то вроде.

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

Вот пример схемыФайл .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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...