Generate migrations outside Rails - activerecord

I'm using ActiveRecord outside Rails. I would want a program to generate the skeleton of a migration ( as well as a system to collect and maintain them ).
Can anyone make a suggestion?

Also take a look at new active_record_migrations

There is a gem to use Rails Database Migrations in non Rails projects. Its name is "standalone_migrations"
Here is a link
https://github.com/thuss/standalone-migrations

If you do not like to use rake, but still get the system part of ActiveRecord::Migration, then you can use the following to handle the ups and downs from plain ruby (without any rails):
require 'active_record'
require 'benchmark'
# Migration method, which does not uses files in db/migrate but in-memory migrations
# Based on ActiveRecord::Migrator::migrate
def migrate(migrations, target_version = nil)
direction = case
when target_version.nil?
:up
when (ActiveRecord::Migrator::current_version == target_version)
return # do nothing
when ActiveRecord::Migrator::current_version > target_version
:down
else
:up
end
ActiveRecord::Migrator.new(direction, migrations, target_version).migrate
puts "Current version: #{ActiveRecord::Migrator::current_version}"
end
# MigrationProxy deals with loading Migrations from files, we reuse it
# to create instances of the migration classes we provide
class MigrationClassProxy < ActiveRecord::MigrationProxy
def initialize(migrationClass, version)
super(migrationClass.name, version, nil, nil)
#migrationClass = migrationClass
end
def mtime
0
end
def load_migration
#migrationClass.new(name, version)
end
end
# Hash of all our migrations
migrations = {
2016_08_09_2013_00 =>
class CreateSolutionTable < ActiveRecord::Migration[5.0]
def change
create_table :solution_submissions do |t|
t.string :problem_hash, index: true
t.string :solution_hash, index: true
t.float :resemblance
t.timestamps
end
end
self # Necessary to get the class instance into the hash!
end,
2016_08_09_2014_16 =>
class CreateProductFields < ActiveRecord::Migration[5.0]
# ...
self
end
}.map { |key,value| MigrationClassProxy.new(value, key) }
ActiveRecord::Base.establish_connection(
:adapter => 'sqlite3',
:database => 'XXX.db'
)
# Play all migrations (rake db:migrate)
migrate(migrations, migrations.last.version)
# ... or undo them (rake db:migrate VERSION=0)
migrate(migrations, 0)
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
class SolutionSubmission < ApplicationRecord
end

I have made a minimal example of how to use active record outside of Rails. Rails migrations (Standalone migrations) in non-Rails (and non Ruby) projects.
https://github.com/euclid1990/rails-migration
(Support Rails >= 5.2)
You can refer Rake file in this repo.

There is another gem called otr-activerecord. This gem provides following tasks:
rake db:create
rake db:create_migration[name]
rake db:drop
rake db:environment:set
rake db:fixtures:load
rake db:migrate
rake db:migrate:status
rake db:rollback
rake db:schema:cache:clear
rake db:schema:cache:dump
rake db:schema:dump
rake db:schema:load
rake db:seed
rake db:setup
rake db:structure:dump
rake db:structure:load
rake db:version
All you need to do is to install it and add a Rakefile with content
load 'tasks/otr-activerecord.rake'
OTR::ActiveRecord.configure_from_file! 'config/database.yml'
I prefer this gem over active_record_migrations or Standalone Migration because those two gems depend on railties, which is almost the entire Rails. For example, Nokogiri takes a long time to compile, and takes a lot of spaces.

Related

Rake not running any tests with minitest

I have a file containing a class of multiple tests (using minitest). I have require 'minitest/autorun' at the top of the file and all tests run correctly when I call the file directly (ruby my_tests.rb).
So far, so good. However, now I'm trying to run my tests via rake.
require "rake/testtask"
task :default => [:test]
Rake::TestTask.new do |t|
t.libs << Dir.pwd + "/lib/examples"
t.test_files = FileList['test/test*.rb']
end
Calling rake shows test/my_test.rb getting called but no tests within the class get run (0 tests, 0 assertions, etc.). I do get these warnings:
...gems/minitest-5.8.0/lib/minitest/assertions.rb:17: warning: already initialized constant MiniTest::Assertions::UNDEFINED
...ruby/2.1.0/lib/ruby/2.1.0/minitest/unit.rb:80: warning: previous definition of UNDEFINED was here
How can I run my tests within rake successfully? I am not using rails.
EDIT: Here is the top of my test file:
require 'minitest/spec'
require 'minitest/autorun'
require 'minitest/reporters'
reporter_options = { color: true }
Minitest::Reporters.use![Minitest::Reporters::DefaultReporter.new(reporter_options)]
class Test_PowerSpecInputs < Minitest::Test
def setup
#mc = TestClass.new()
end
def test_does_lib_have_constant
# my test code
end
end
Try changing your Rakefile to this.
require "bundler/gem_tasks"
require "rake/testtask"
Rake::TestTask.new(:test) do |t|
t.libs << "test"
t.libs << "lib"
t.test_files = FileList['test/**/*_test.rb']
end
task :default => :test
jphager2 got me thinking about tool versions and it turned out that my version of rake was fairly old. Updating to 11.x did the trick.

Codeship, Sinatra, ActiveRecord - configuration

I have a sinatra app working on my computer and am trying to get the tests to run on Codeship. I've reduced it to a tiny subset to see if I can sort out the problem I am having. I would greatly appreciate another pair of eyes...
Here are the key files:
Rakefile:
require 'sinatra/activerecord/rake'
require 'rake/testtask'
require_relative "demo_app"
Rake::TestTask.new do |t|
t.pattern = "test/*_test.rb"
end
database.yml
development:
adapter: sqlite3
database: db/development.sqlite3
test:
adapter: sqlite3
database: db/test.sqlite3
production:
url: <%= ENV['DATABASE_URL'] %>
demo_app.rb:
require 'sinatra/activerecord'
require './models/event'
require './models/person'
require './models/registration'
require 'pry-byebug'
migrations:
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
t.string :name
t.date :date
end
end
end
test_helper.rb:
ENV['RACK_ENV'] = "test"
ENV["SINATRA_ENV"] = "test"
require_relative '../demo_app'
require 'minitest/autorun'
require 'rack/test'
ActiveRecord::Migration.maintain_test_schema!
event_test.rb:
require_relative './test_helper.rb'
describe Event do
it "can add events" do
Event.create(name: "An Event")
Event.create(name: "Another Event")
Event.all.size.must_equal 2
end
end
So, with that context I setup Codeship. Here are the key settings there:
Setup commands:
rvm use 2.2.2
bundle install
RACK_ENV=test bundle exec rake db:migrate
Test Pipeline (1 of 1)
rake test
And now when I push to git, and codeship picks it up I get this error on line 1 of demo_app.rb which is a require to sinatra/activerecord:
rake aborted!
Database URL cannot be empty
.....
It seems that for some reason, it is not paying attention to the fact that I am running in test mode and so it should use the test clause of database.yml.
Thoughts?

Sinatra db table not created after migration

I am trying to create active record using Sinatra and Sinatra/active record, my migrations are getting migrated to the Postgres database but tables are not getting created in the database, I went through all the possible solutions on stack overflow but its of no use. I tried even deleting my migration files from db/migrate folder but still the same output. What must be the error
Gemfile
source 'https://rubygems.org'
gem "sinatra"
gem "pg" #for postgres
gem "activerecord"
gem "sinatra-activerecord"
config.ru
require "./app"
run Sinatra::Application
rakefile.rb
require "./app"
require "sinatra/activerecord/rake"
app.rb
require 'sinatra'
require 'sinatra/activerecord'
db = URI.parse('postgres://project1:project1#localhost/*****')
ActiveRecord::Base.establish_connection(
:adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
:host => db.host,
:username => db.user,
:password => db.password,
:database => db.path[1..-1],
:encoding => 'utf8'
)
class Note < ActiveRecord::Base
end
class CreateNotes < ActiveRecord::Migration
def up
create_table :notes do |t|
t.string :title
t.text :body
t.timestamps
end
end
def down
drop_table :notes
end
end
output of migration
user#user-Inspiron-5520:~/rails-apps/project1$ rake db:migrate
== 20150704053019 CreateNotes: migrating ======================================
== 20150704053019 CreateNotes: migrated (0.0000s) =============================
db output (psql)
\dt
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+-----------
public | schema_migrations | table | project1
(1 row)
project1=# select * from schema_migrations;
version
----------------
20150704053019
(1 row)
note: Project1 user is a super user with all privileges
EDIT
Migrations file 20150704053019_create_notes.rb
class CreateNotes < ActiveRecord::Migration
def change
end
end
I would first like to note that #limekin was the first to get the answer, commenting:
The migration you are using to create notes table is actually kept in app.rb. But the migrate task looks for migrations inside db/migrate. If the migration file you gave at the bottom is inside the right directory, then move the migration definition from app.rb to there.
I will just go into a bit more detail. The function that you are using to create the table belongs in the migration file, because a migration is what creates, changes and deletes tables, columns, and records.
So to solve your issue just move the function up in your app file into the change function in your migration file.

Tests within Gem need to test migration generator and apply migrations for tests

I'm working on a Gem that contains a migration generator and a bunch of models, classes, etc that utilize the tables created as part of the migration.
Although testing the migration generator itself is easy enough - there's loads of tutorials around for getting that done, what i'm trying to work out is how to actually run the migration on the test DB so I can later test how the gem interacts with the test data?
Since the gem doesn't have a schema.rb, I wasn't sure how to go about doing it.
This is how I run migrations in code;
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
ActiveRecord::Migration.verbose = false
#migration = Class.new(ActiveRecord::Migration) do
def change
create_table :users, :force => true do |t|
t.string :roles_mask
end
create_table :user_without_roles, :force => true do |t|
t.string :roles_mask
end
create_table :user_without_role_masks, :force => true do |t|
end
end
end
#migration.new.migrate(:up)
If you have a string containing your generated migration you could do something like this in your test setup;
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
ActiveRecord::Migration.verbose = false
# Or however you intend to grab the output of the migration generator
migration_string = ERB.new(File.read(<file name here>)).result
migration = Class.new(ActiveRecord::Migration)
migration.class_eval(migration_string)
migration.new.migrate(:up)
That should give you a migrated database using the migration you've generated.
You can do something like this:
I am going to assume you're using ActiveRecord. So in your test helper you should setup a in-memory database:
require 'active_record'
# Connection must be establised before anything else
ActiveRecord::Base.establish_connection(
:adapter => defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3',
:database => ':memory:'
)
Then invoke the rake task within your test. This would look something like:
require 'rake'
requie File.expand_path('../Rakefile', __FILE__) # you'll need to modify this path to actually point to the Rakefile
Rake::Task['db:migrate'].invoke
The rake taks invocation is untested, but that should point you in the right direction.
The other option would be to just run the command:
%x{rake db:migrate}

How do I log queries in a rake task using datamapper and padrino?

I have a padrino install that is using datamapper and logging queries to a file. This is working fine when browsing my application. But queries are not logged if executed inside a rake file. Why?
This is how the task is defined:
# lib/tasks/example.rake
task :example => :environment do
players = Player.all #Player is a datamapper object
puts players.first.to_s
end
I also added this line to /config/boot.rb
Padrino::Logger::Config[:development] = { :log_level => :devel, :stream => :to_file }
And this line is called in /config/database.rb
DataMapper.logger = logger
And this is how I'm executing the script
$ padrino rake example
Invoke rake with:
PADRINO_LOG_LEVEL=development padrino rake my:task

Resources