2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Sinatra】Active Recordでつまずいた!~解決編

Posted at

こちらの記事の続きです。

Sinatraでrakeファイルに記述したActive Recordを使用し、bundle exec rake~でrakeファイル記述した内容を実行しようとした際に出たエラーの内容に関する記事です。

エラー内容は
cannot load such file -- sinatra/activerecord
という内容で、ログに表現されている内容はとても簡単で、sinatra/activerecordなんてねーよって意味です。けっこうな量の記事通りにsinatraのアプリを組んでも、このエラーが出るので、自分のPCの環境がよくないのかなとも思っています。ちなみにWin10を使用しています。

*参考
https://railsgirls-bne.github.io/sinatra-app-guide
https://github.com/janko/sinatra-activerecord

Gemfileの作成

Gemfile

source 'https://rubygems.org'

gem 'sqlite3'
gem 'rake'
gem 'sinatra'
gem 'sinatra-activerecord', path: ".."
gem 'activerecord'
gem 'pry'
gem 'pry-byebug'

bundle install しましょう。

Rakefileの作成

Rakefile

require 'sinatra/activerecord' 
require 'sinatra/activerecord/rake'

namespace :db do
    task :load_config do
      require "./app"
    end
  end

Rakefileの内容です。

sinatraフォルダの作成

sinatra フォルダを作りましょう!

その配下にactiverecord.rb ファイルを作成します。

sinatra/activerecord.rb
require 'sinatra/base'
require 'active_record'
require 'active_support/core_ext/hash/keys'

require 'logger'
require 'pathname'
require 'yaml'
require 'erb'

module Sinatra
  module ActiveRecordHelper
    def database
      settings.database
    end
  end

  module ActiveRecordExtension
    def self.registered(app)
      if ENV['DATABASE_URL']
        app.set :database, ENV['DATABASE_URL']
      elsif File.exist?("#{Dir.pwd}/config/database.yml")
        app.set :database_file, "#{Dir.pwd}/config/database.yml"
      end

      unless defined?(Rake) || [:test, :production].include?(app.settings.environment)
        ActiveRecord::Base.logger = Logger.new(STDOUT)
      end

      app.helpers ActiveRecordHelper

      # re-connect if database connection dropped (Rails 3 only)
      app.before { ActiveRecord::Base.verify_active_connections! if ActiveRecord::Base.respond_to?(:verify_active_connections!) }
      app.after { ActiveRecord::Base.clear_active_connections! }
    end

    def database_file=(path)
      path = File.join(root, path) if Pathname(path).relative? and root
      spec = YAML.load(ERB.new(File.read(path)).result) || {}
      set :database, spec
    end

    def database=(spec)
      if spec.is_a?(Hash) and spec.symbolize_keys[environment.to_sym]
        ActiveRecord::Base.configurations = spec.stringify_keys
        ActiveRecord::Base.establish_connection(environment.to_sym)
      elsif spec.is_a?(Hash)
        ActiveRecord::Base.configurations[environment.to_s] = spec.stringify_keys
        ActiveRecord::Base.establish_connection(spec.stringify_keys)
      else
        ActiveRecord::Base.establish_connection(spec)
        ActiveRecord::Base.configurations ||= {}
        ActiveRecord::Base.configurations[environment.to_s] = ActiveRecord::ConnectionAdapters::ConnectionSpecification::ConnectionUrlResolver.new(spec).to_hash
      end
    end

    def database
      ActiveRecord::Base
    end
  end

  register ActiveRecordExtension
end

そして、sinatra フォルダ配下にactiverecord フォルダを作成します。

sinatra/activerecord の配下にrake.rb と、tasks.rake を作成します。

rake.rb
load "active_record/railties/databases.rake"
require "sinatra/activerecord/rake/activerecord_#{ActiveRecord::VERSION::MAJOR}"

load "sinatra/activerecord/tasks.rake"

ActiveRecord::Base.logger = nil
tasks.rake
require "active_support/core_ext/string/strip"
require "pathname"
require "fileutils"

namespace :db do
  desc "Create a migration (parameters: NAME, VERSION)"
  task :create_migration do
    unless ENV["NAME"]
      puts "No NAME specified. Example usage: `rake db:create_migration NAME=create_users`"
      exit
    end

    name    = ENV["NAME"]
    version = ENV["VERSION"] || Time.now.utc.strftime("%Y%m%d%H%M%S")

    ActiveRecord::Migrator.migrations_paths.each do |directory|
      next unless File.exist?(directory)
      migration_files = Pathname(directory).children
      if duplicate = migration_files.find { |path| path.basename.to_s.include?(name) }
        puts "Another migration is already named \"#{name}\": #{duplicate}."
        exit
      end
    end

    filename = "#{version}_#{name}.rb"
    dirname  = ActiveRecord::Migrator.migrations_paths.first
    path     = File.join(dirname, filename)
    ar_maj   = ActiveRecord::VERSION::MAJOR
    ar_min   = ActiveRecord::VERSION::MINOR
    base     = "ActiveRecord::Migration"
    base    += "[#{ar_maj}.#{ar_min}]" if ar_maj >= 5

    FileUtils.mkdir_p(dirname)
    File.write path, <<-MIGRATION.strip_heredoc
      class #{name.camelize} < #{base}
        def change
        end
      end
    MIGRATION

    puts path
  end
end

# The `db:create` and `db:drop` command won't work with a DATABASE_URL because
# the `db:load_config` command tries to connect to the DATABASE_URL, which either
# doesn't exist or isn't able to drop the database. Ignore loading the configs for
# these tasks if a `DATABASE_URL` is present.
if ENV.has_key? "DATABASE_URL"
  Rake::Task["db:create"].prerequisites.delete("load_config")
  Rake::Task["db:drop"].prerequisites.delete("load_config")
end

sinatra/activerecord の配下に、rake フォルダを作成します。

rake フォルダの配下にactiverecord_"Active Recordのver".rb を作成します。
私の場合はActive Record6なので、activerecord_6.rb になります。

activerecord_6.rb
seed_loader = Class.new do
  def load_seed
    load "#{ActiveRecord::Tasks::DatabaseTasks.db_dir}/seeds.rb"
  end
end

ActiveRecord::Tasks::DatabaseTasks.tap do |config|
  config.root                   = Rake.application.original_dir
  config.env                    = ENV["RACK_ENV"] || "development"
  config.db_dir                 = "db"
  config.migrations_paths       = ["db/migrate"]
  config.fixtures_path          = "test/fixtures"
  config.seed_loader            = seed_loader.new
  config.database_configuration = ActiveRecord::Base.configurations
end

# db:load_config can be overriden manually
Rake::Task["db:seed"].enhance(["db:load_config"])
Rake::Task["db:load_config"].clear

# define Rails' tasks as no-op
Rake::Task.define_task("db:environment")
Rake::Task["db:test:deprecated"].clear if Rake::Task.task_defined?("db:test:deprecated")

これでsinatra フォルダの内容は出来上がりました。

databaseの設定

config フォルダを作成し、その配下にdatabase.yml を作成します。

config/database.yml
development:
  adapter: sqlite3
  database: db/development.sqlite3

test:
  adapter: sqlite3
  database: db/test.sqlite3

これで基本的な設定は完成です。

bundle exec rake -T コマンドで、使用できるタスクが表示されるはずです。

rake db:create              # Creates the database from DATABASE_URL or con...
rake db:create_migration    # Create a migration (parameters: NAME, VERSION)
rake db:drop                # Drops the database from DATABASE_URL or confi...
rake db:environment:set     # Set the environment value for the database
rake db:fixtures:load       # Loads fixtures into the current environment's...
rake db:migrate             # Migrate the database (options: VERSION=x, VER...
rake db:migrate:status      # Display status of migrations
rake db:prepare             # Runs setup if database does not exist, or run...
rake db:rollback            # Rolls the schema back to the previous version...
rake db:schema:cache:clear  # Clears a db/schema_cache.yml file
rake db:schema:cache:dump   # Creates a db/schema_cache.yml file
rake db:schema:dump         # Creates a db/schema.rb file that is portable ...
rake db:schema:load         # Loads a schema.rb file into the database
rake db:seed                # Loads the seed data from db/seeds.rb
rake db:seed:replant        # Truncates tables of each database for current...
rake db:setup               # Creates the database, loads the schema, and i...
rake db:structure:dump      # Dumps the database structure to db/structure.sql
rake db:structure:load      # Recreates the databases from the structure.sq...
rake db:version             # Retrieves the current schema version number

マイグレーションファイルの作成

bundle exec rake db:create_migration NAME=create_ideas で、マイグレーションファイルの作成を行います。

20190823054856_create_ideas.rb のように、日付入りのファイルが出来上がると思います。

class CreateIdeas < ActiveRecord::Migration[6.0]
  def change
    create_table :ideas do |t|
      t.string :name
      t.text :description
      t.string :picture

      t.timestamps null: false
    end
  end
end

出来上がったマイグレーションファイルに修正を加えます。
特に、class CreateIdeas < ActiveRecord::Migration[6.0][6.0] を忘れないようにしましょう!

最後にbundle exec rake db:migrate でマイグレーションを実行し、完了です。

まとめ

ここまで調べるのに長くかかりました。。。
でも、調べ方が上手くなったのでよかったです!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?