monark 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Changelog.md ADDED
@@ -0,0 +1,5 @@
1
+ # Monark Changelog
2
+
3
+ ## 0.0.1
4
+
5
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,9 @@
1
+ Copyright (c) 2013 Norman Clarke and Flexminder Inc
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # Monark
2
+
3
+ Monark is a database migrator and seeder, intended to supplement Active
4
+ Record's migrations and replace Rails's seed tasks.
5
+
6
+ It keeps track of which SQL or Ruby code has been run on your database so that
7
+ you can change make incremental changes to your production database without
8
+ having to run ad-hoc deployment scripts.
9
+
10
+ Why "Monark?" I wanted to call it "Monarch" but the name was taken and I
11
+ couldn't think of anything better.
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ gem 'monark'
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install monark
26
+
27
+ ## Usage
28
+
29
+ Read [this file](https://github.com/flexminder/monark/blob/master/lib/generators/templates/Migrations.rb) for information on how to set up Monark.
30
+
31
+ ### Setup
32
+
33
+ rails generate monark
34
+ edit db/monark/Migrations.rb
35
+ add migrations to db/monark
36
+
37
+ ### Tasks
38
+
39
+ # rake monark:assume_done # Assume all migrations have been performed
40
+ # rake monark:migrate # Perform pending migrations
41
+ # rake monark:reload # Perform reloadable and pending migrations
42
+ # rake monark:reset # Perform all migrations again
43
+
44
+
45
+ If you're porting your seeds or other existing database management code to
46
+ Monark, you'll probably want add your existing seeds, deploy and peform `rake monark:assume_done` to make sure you don't overwrite anything in production.
47
+
48
+ Then you can safely add more migrations and deploy them with
49
+ `rake monark:migrate`.
50
+
51
+ ## Deficiencies
52
+
53
+ It only works with Active Record for now, since this is what we currently need
54
+ at FlexMinder. Support for other database libraries would be nice to have but
55
+ we probably won't add that until we need it ourselves.
56
+
57
+ ## Contributing
58
+
59
+ 1. Fork it
60
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
61
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
62
+ 4. Push to the branch (`git push origin my-new-feature`)
63
+ 5. Create new Pull Request
64
+
65
+ ## License
66
+
67
+ Copyright (c) 2013 Norman Clarke and Flexminder Inc.
68
+
69
+ MIT License
70
+
71
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
72
+ this software and associated documentation files (the "Software"), to deal in
73
+ the Software without restriction, including without limitation the rights to
74
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
75
+ of the Software, and to permit persons to whom the Software is furnished to do
76
+ so, subject to the following conditions:
77
+
78
+ The above copyright notice and this permission notice shall be included in all
79
+ copies or substantial portions of the Software.
80
+
81
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
83
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
84
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
85
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
86
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
87
+ SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require "rake/testtask"
2
+ require "rake/clean"
3
+
4
+ CLEAN.replace Rake::FileList['**/*.gem', 'doc', 'coverage']
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList['test/**/*_test.rb']
9
+ end
10
+
11
+ task :default => :test
12
+
13
+ task :gem do
14
+ sh 'gem build monark.gemspec'
15
+ end
@@ -0,0 +1,9 @@
1
+ require 'rails/generators'
2
+
3
+ class MonarkGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+
6
+ def install
7
+ copy_file "Migrations.rb", "db/monark/Migrations.rb"
8
+ end
9
+ end
@@ -0,0 +1,42 @@
1
+ # Migrations.rb
2
+ #
3
+ # This file was generated by Monark and is used to manage seeds and database
4
+ # changes that Active Record Migrations don't handle very well.
5
+ #
6
+ # You can manage Monark with the following rake tasks:
7
+ #
8
+ # rake monark:assume_done # Assume all migrations have been performed
9
+ # rake monark:migrate # Perform pending migrations
10
+ # rake monark:reload # Perform reloadable and pending migrations
11
+ # rake monark:reset # Perform all migrations again
12
+ #
13
+ # In your Migrations.rb file itself, you can break your modifications up into
14
+ # groups used in different environments. This lets you load specific development
15
+ # or test fixtures that share some data with production (i.e., a list of
16
+ # countries for a form select), but also have some fake data you want to keep
17
+ # out of production (i.e., fake application users).
18
+ groups :development, :production do
19
+
20
+ # The `add` method applies code that is only loaded once, ever, unless you're
21
+ # resetting your database. This is good for seed data or for altering your
22
+ # schema.
23
+ #
24
+ # Here, `foo` should be a file in db/monark. Various file types are supported,
25
+ # plain .sql files, .sql.erb files which are passed through Erb before
26
+ # loading, and plain .rb files.
27
+ add 'foo'
28
+
29
+ # The `load` method applies code that can be reloaded. This is good for stored
30
+ # procedures, which are application code that may be changed. You need to take
31
+ # care that any file you pass as an argument here is safe to reload; for
32
+ # example, any CREATE FUNCTION should probably have a corresponding DROP
33
+ # FUNCTION.
34
+ load 'bar'
35
+ end
36
+
37
+ # You can invoke a block of Ruby code with `add` or `load`. You can pass a
38
+ # group or groups as a hash option, or organize them in blocks like in the
39
+ # example above.
40
+ add 'say hello', :group => :test do
41
+ puts 'hello world!'
42
+ end
@@ -0,0 +1,61 @@
1
+ module Monark
2
+
3
+ # Monark runtime. Encapsulates state and manages migrations.
4
+ class Context
5
+ attr_accessor :root, :env, :migrations_file_name, :connection
6
+ attr_reader :migrations, :version
7
+ attr_writer :manifest
8
+
9
+ def initialize(root, migrations_file_name = Monark::DEFAULT_MIGRATIONS_FILE_NAME)
10
+ self.root = Pathname.new(root)
11
+ self.migrations_file_name = migrations_file_name
12
+ @migrations = []
13
+ @env = Monark.env
14
+ end
15
+
16
+ def manifest
17
+ @manifest ||= root.join(migrations_file_name).read
18
+ end
19
+
20
+ def version=(number)
21
+ @version = Integer(number)
22
+ end
23
+
24
+ def load_manifest
25
+ @loaded_manifest ||= begin
26
+ DSL.new(self).instance_eval(manifest, root.join(migrations_file_name).to_s, 0)
27
+ true
28
+ end
29
+ end
30
+
31
+ def push(*args)
32
+ migrations.push(*args)
33
+ end
34
+
35
+ def done
36
+ load_manifest
37
+ count = migrations.count
38
+ schema = Schema.new
39
+ schema.next_migration = count if count > schema.next_migration
40
+ end
41
+
42
+ def assume_done
43
+ load_manifest
44
+ schema = Schema.new
45
+ schema.next_migration = migrations.count
46
+ end
47
+
48
+ def migrate(options = {})
49
+ load_manifest
50
+ schema = Schema.new
51
+ ActiveRecord::Base.transaction do
52
+ migrations.each_with_index do |migration, index|
53
+ if (index >= schema.next_migration) || (migration.reloadable? && options[:reload])
54
+ migration.perform
55
+ end
56
+ end
57
+ done
58
+ end
59
+ end
60
+ end
61
+ end
data/lib/monark/dsl.rb ADDED
@@ -0,0 +1,35 @@
1
+ module Monark
2
+
3
+ # The Monark DSL.
4
+ class DSL
5
+ extend Forwardable
6
+
7
+ attr_reader :_context
8
+
9
+ def initialize(context = nil)
10
+ @_context = context
11
+ end
12
+
13
+ def groups(*args, &block)
14
+ groups = args.flatten.compact
15
+ yield if groups.empty? || groups.include?(_context.env.to_sym)
16
+ end
17
+ alias group groups
18
+
19
+ def set_version(arg)
20
+ _context.version = arg
21
+ end
22
+
23
+ def add(name, options = {}, &block)
24
+ groups(options.fetch(:group, options[:groups])) do
25
+ _context.push Migration.new(_context.root, name, block)
26
+ end
27
+ end
28
+
29
+ def load(name, options = {}, &block)
30
+ add(name, options, &block)
31
+ _context.migrations.last.reloadable = true
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,46 @@
1
+ module Monark
2
+
3
+ # A Monark migration. Acceptable formats are `.sql`, `.sql.erb` and `.rb`.
4
+ class Migration
5
+
6
+ attr_accessor :root, :path, :kind, :reloadable
7
+ alias reloadable? reloadable
8
+
9
+ def initialize(root, path, proc = nil)
10
+ self.root = Pathname(root.to_s)
11
+ self.path = path
12
+ @code = proc
13
+ end
14
+
15
+ def code
16
+ @code ||= load_file("sql", "sql.erb", "rb")
17
+ end
18
+
19
+ def perform
20
+ code
21
+ if !kind
22
+ puts "-> calling '#{@path}'"
23
+ @code.call
24
+ elsif @kind == "rb"
25
+ puts "-> evaluating '#{@path}'"
26
+ binding.eval(@code, path, 0)
27
+ else
28
+ puts "-> executing '#{@path}'"
29
+ ActiveRecord::Base.connection.execute @code
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def load_file(*extensions)
36
+ extensions.each do |ext|
37
+ file = root.join("#{path}.#{ext}")
38
+ if file.readable?
39
+ data = file.read
40
+ @kind = ext.gsub(/\.erb\z/, '')
41
+ return ext =~ /\.erb\z/ ? ERB.new(data).result(binding) : data
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ module Monark
2
+
3
+ # Monark's Railtie.
4
+ class Railtie < Rails::Railtie
5
+ load 'monark/tasks.rake'
6
+ end
7
+ end
@@ -0,0 +1,48 @@
1
+ module Monark
2
+
3
+ # The Monark schema. Creates and updates the schema in an SQL database.
4
+ class Schema
5
+
6
+ attr_accessor :context
7
+ attr_reader :version, :next_migration
8
+
9
+ def initialize
10
+ load_info
11
+ end
12
+
13
+ def next_migration=(value)
14
+ value = Integer(value)
15
+ conn.execute "UPDATE monark_info SET next_migration = #{value}"
16
+ @next_migration = value
17
+ end
18
+
19
+ private
20
+
21
+ def create_table_if_not_exists
22
+ conn.execute 'CREATE TABLE IF NOT EXISTS monark_info(version integer NOT NULL, next_migration integer NOT NULL)'
23
+ end
24
+
25
+ def get_first_row
26
+ result = conn.select_all 'SELECT version, next_migration FROM monark_info LIMIT 1'
27
+ if result.empty?
28
+ @version = 1
29
+ @next_migration = 0
30
+ conn.execute "INSERT INTO monark_info (version, next_migration) VALUES (#{@version}, #{@next_migration})"
31
+ else
32
+ @version = Integer(result[0]['version'])
33
+ @next_migration = Integer(result[0]['next_migration'])
34
+ end
35
+ end
36
+
37
+ def load_info
38
+ conn.transaction do
39
+ create_table_if_not_exists
40
+ get_first_row
41
+ end
42
+ end
43
+
44
+ def conn
45
+ ActiveRecord::Base.connection
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,35 @@
1
+ namespace :monark do
2
+
3
+ def monark_root
4
+ @monark_root ||= Rails.root.join("db/monark")
5
+ end
6
+
7
+ desc 'Perform pending migrations'
8
+ task :migrate => :environment do
9
+ context = Monark::Context.new monark_root
10
+ context.migrate
11
+ end
12
+
13
+ desc 'Perform reloadable and pending migrations'
14
+ task :reload => :environment do
15
+ context = Monark::Context.new monark_root
16
+ context.migrate(:reload => true)
17
+ end
18
+
19
+ desc 'Perform all migrations again'
20
+ task :reset => :environment do
21
+ ActiveRecord::Base.connection.transaction do
22
+ schema = Monark::Schema.new
23
+ schema.next_migration = 0
24
+ Rake::Task['monark:migrate'].invoke
25
+ end
26
+ end
27
+
28
+ desc 'Assume all migrations have been performed'
29
+ task :assume_done => :environment do
30
+ context = Monark::Context.new monark_root
31
+ context.assume_done
32
+ schema = Monark::Schema.new
33
+ puts "Next migration set to #{schema.next_migration}"
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module Monark
2
+ VERSION = '0.0.1'
3
+ end
data/lib/monark.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'erb'
2
+ require 'forwardable'
3
+
4
+ require 'active_record'
5
+
6
+ require 'monark/context'
7
+ require 'monark/schema'
8
+ require 'monark/dsl'
9
+ require 'monark/migration'
10
+ require 'monark/version'
11
+
12
+ if defined?(Rails)
13
+ require 'monark/railtie'
14
+ end
15
+
16
+ # Monark is a simple migrator.
17
+ module Monark
18
+
19
+ DEFAULT_MIGRATIONS_FILE_NAME = 'Migrations.rb'
20
+ DEFAULT_ENV = 'development'
21
+
22
+ def self.env
23
+ if ENV.key?('MONARK_ENV')
24
+ ENV['MONARK_ENV']
25
+ elsif defined?(::Rails)
26
+ ::Rails.env.to_s
27
+ elsif ENV.key?('RACK_ENV')
28
+ ENV['RACK_ENV']
29
+ else
30
+ DEFAULT_ENV.to_s
31
+ end
32
+ end
33
+ end
data/monark.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'monark/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'monark'
8
+ spec.version = Monark::VERSION
9
+ spec.authors = ['Norman Clarke']
10
+ spec.email = ['norman@njclarke.com']
11
+ spec.description = 'A simple migrator/seeder'
12
+ spec.summary = 'A simple migrator/seeder'
13
+ spec.homepage = 'https://github.com/flexminder/monark'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.test_files = spec.files.grep(%r{^test/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency 'activerecord'
21
+ spec.add_development_dependency 'sqlite3'
22
+ spec.add_development_dependency 'bundler', "~> 1.3"
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'minitest'
25
+ end
@@ -0,0 +1,12 @@
1
+ set_version 42
2
+
3
+ group :development do
4
+ add 'foo'
5
+ end
6
+
7
+ groups :development, :test do
8
+ add 'bar'
9
+ load 'baz'
10
+ end
11
+
12
+ add 'foo2', :group => :production
@@ -0,0 +1 @@
1
+ INSERT INTO <%= Thread.current[:table] %> VALUES (1);
@@ -0,0 +1 @@
1
+ Thread.current[:hello] = 'world'
@@ -0,0 +1 @@
1
+ CREATE TABLE foo (a_col INTEGER);
data/test/helper.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'ostruct'
4
+ require 'set'
5
+ require 'active_record'
6
+
7
+ $VERBOSE = true
8
+
9
+ require 'monark'
10
+
11
+ class Module
12
+ def test(name, &block)
13
+ define_method "test #{name}", block
14
+ end
15
+ end
16
+
17
+ class Monark::Migration
18
+ def puts(*args); end
19
+ end
20
+
21
+ connection_params = {
22
+ :adapter => 'sqlite3',
23
+ :database => ':memory:',
24
+ :encoding => 'utf8'
25
+ }
26
+
27
+ ActiveRecord::Base.establish_connection connection_params
28
+
29
+ module Monark
30
+ module TestHelp
31
+ def fixtures_path
32
+ Pathname(File.expand_path("../fixtures", __FILE__))
33
+ end
34
+
35
+ def context
36
+ @context ||= Context.new('/tmp')
37
+ end
38
+
39
+ def transaction
40
+ ActiveRecord::Base.transaction { yield ; raise ActiveRecord::Rollback }
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,127 @@
1
+ require 'helper'
2
+
3
+ module Monark
4
+ class ContextTest < MiniTest::Unit::TestCase
5
+
6
+ include TestHelp
7
+
8
+ def teardown
9
+ # TODO: Add as method to Schema class
10
+ ActiveRecord::Base.connection.execute "DROP TABLE IF EXISTS monark_info"
11
+ Thread.current[:counter] = nil
12
+ end
13
+
14
+ test 'should perform migrations' do
15
+ Thread.current[:table] = 'foo'
16
+ transaction do
17
+ context = Context.new(fixtures_path)
18
+ context.migrate
19
+ schema = Schema.new
20
+ assert_equal 3, schema.next_migration
21
+ assert_equal 1, schema.version
22
+ end
23
+ end
24
+
25
+ test '#done should set the next migration past the current ones' do
26
+ transaction do
27
+ context = Context.new(fixtures_path)
28
+ context.done
29
+ assert_equal 3, Schema.new.next_migration
30
+ end
31
+ end
32
+
33
+ test '#migrate should skip completed migrations' do
34
+ transaction do
35
+ schema = Schema.new
36
+ schema.next_migration = 1
37
+ context = Context.new(fixtures_path)
38
+ Thread.current[:counter] = 0
39
+ context.manifest = <<-END
40
+ add 'foo' do
41
+ Thread.current[:counter] = Thread.current[:counter].next
42
+ end
43
+ add 'bar' do
44
+ Thread.current[:counter] = Thread.current[:counter].next
45
+ end
46
+ add 'baz' do
47
+ Thread.current[:counter] = Thread.current[:counter].next
48
+ end
49
+ END
50
+ context.migrate
51
+ assert_equal 2, Thread.current[:counter]
52
+ end
53
+ end
54
+
55
+ test '#migrate should optionally reload migrations added with load' do
56
+ transaction do
57
+ schema = Schema.new
58
+ schema.next_migration = 100
59
+ context = Context.new(fixtures_path)
60
+ Thread.current[:counter] = 0
61
+ context.manifest = <<-END
62
+ load 'foo' do
63
+ Thread.current[:counter] = Thread.current[:counter].next
64
+ end
65
+ END
66
+ context.migrate
67
+ assert_equal 0, Thread.current[:counter]
68
+ assert_equal 100, schema.next_migration
69
+ context.migrate(:reload => true)
70
+ assert_equal 100, schema.next_migration
71
+ assert_equal 1, Thread.current[:counter]
72
+ end
73
+ end
74
+
75
+ test 'should have a default migrations file name' do
76
+ assert_equal 'Migrations.rb', DEFAULT_MIGRATIONS_FILE_NAME
77
+ end
78
+
79
+ test 'constructor should set a root Pathname' do
80
+ assert_equal Pathname, context.root.class
81
+ assert_equal '/tmp', context.root.to_s
82
+ end
83
+
84
+ test 'constructor should set a migrations file name' do
85
+ context = Context.new('/tmp', 'foo.rb')
86
+ assert_equal 'foo.rb', context.migrations_file_name
87
+ end
88
+
89
+ test 'constructor should set default migrations file name' do
90
+ assert_equal DEFAULT_MIGRATIONS_FILE_NAME, context.migrations_file_name
91
+ end
92
+
93
+ test 'should load the migrations file as the manifest' do
94
+ context = Context.new(fixtures_path)
95
+ data = File.read(fixtures_path.join('Migrations.rb'))
96
+ assert_equal data, context.manifest
97
+ end
98
+
99
+ test 'should push to the migrations array' do
100
+ context.push :foo
101
+ assert_equal :foo, context.migrations.first
102
+ end
103
+
104
+ test 'should set version from number or numeric string' do
105
+ context.version = 1
106
+ assert_equal 1, context.version
107
+ context.version = '2'
108
+ assert_equal 2, context.version
109
+ end
110
+
111
+ test 'should raise error if the version can not be cast to a number' do
112
+ begin
113
+ context.version = 'foo'
114
+ flunk 'should have raised an error'
115
+ rescue ArgumentError
116
+ assert true
117
+ end
118
+ end
119
+
120
+ test 'should load manifest' do
121
+ context = Context.new(fixtures_path)
122
+ context.load_manifest
123
+ assert_equal 42, context.version
124
+ assert_equal 3, context.migrations.count
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,62 @@
1
+ require 'helper'
2
+
3
+ module Monark
4
+ class DSLTest < MiniTest::Unit::TestCase
5
+
6
+ test 'set_version should set the version on the context' do
7
+ dsl.set_version 42
8
+ assert_equal 42, context.version
9
+ end
10
+
11
+ test 'add should instantiate a migration and add it to the context' do
12
+ dsl.add "foo"
13
+ assert_equal Migration, context.migrations.first.class
14
+ end
15
+
16
+ test 'add should not add a migration if the group differs from the env' do
17
+ dsl.add "foo", :group => :production
18
+ assert_equal [], context.migrations
19
+ end
20
+
21
+ test 'add should add a migration if the groups is the env' do
22
+ dsl.add "foo", :group => :development
23
+ assert_equal Migration, context.migrations.first.class
24
+ end
25
+
26
+ test 'add should not add a migration if the groups do not include the env' do
27
+ dsl.add "foo", :groups => [:production, :whatever]
28
+ assert_equal [], context.migrations
29
+ end
30
+
31
+ test 'add should add a migration if the groups include the env' do
32
+ dsl.add "foo", :groups => [:production, :development]
33
+ assert_equal Migration, context.migrations.first.class
34
+ end
35
+
36
+ test 'group should yield if the group is the env' do
37
+ dsl.group(:development) {assert true}
38
+ end
39
+
40
+ test 'group should yield if the group differs from the env' do
41
+ dsl.group(:production) {flunk}
42
+ end
43
+
44
+ test 'groups should not yield the groups do not include the env' do
45
+ dsl.groups(:production, :test) {flunk}
46
+ end
47
+
48
+ test 'groups should yield the groups include the env' do
49
+ dsl.groups(:production, :development) {assert true}
50
+ end
51
+
52
+ private
53
+
54
+ def dsl
55
+ @dsl ||= DSL.new(context)
56
+ end
57
+
58
+ def context
59
+ @context ||= Context.new(File.expand_path('../fixtures', __FILE__))
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,34 @@
1
+ require 'helper'
2
+
3
+ module Monark
4
+ class MigrationTest < MiniTest::Unit::TestCase
5
+
6
+ include TestHelp
7
+
8
+ test 'should load SQL' do
9
+ migration = Migration.new(fixtures_path, "foo")
10
+ assert_equal "CREATE TABLE foo (a_col INTEGER);", migration.code
11
+ end
12
+
13
+ test 'should load SQL + Erb' do
14
+ begin
15
+ Thread.current[:table] = "foo"
16
+ migration = Migration.new(fixtures_path, "bar")
17
+ assert_equal "INSERT INTO foo VALUES (1);", migration.code
18
+ ensure
19
+ Thread.current[:table] = nil
20
+ end
21
+ end
22
+
23
+ test 'should load Ruby' do
24
+ migration = Migration.new(fixtures_path, "baz")
25
+ assert_equal %q{Thread.current[:hello] = 'world'}, migration.code
26
+ end
27
+
28
+ test 'should load a proc' do
29
+ migration = Migration.new(fixtures_path, "say hello", -> {puts 'hello world'})
30
+ assert_kind_of Proc, migration.code
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ require 'helper'
2
+
3
+ module Monark
4
+ class SchemaTest < MiniTest::Unit::TestCase
5
+
6
+ include TestHelp
7
+
8
+ test 'should create table and record' do
9
+ transaction do
10
+ schema = Schema.new
11
+ assert_equal 1, schema.version
12
+ assert_equal 0, schema.next_migration
13
+ end
14
+ end
15
+
16
+ test 'should load schema info from existing records' do
17
+ transaction do
18
+ schema = Schema.new
19
+ schema.version
20
+ schema = Schema.new
21
+ assert_equal 1, schema.version
22
+ assert_equal 0, schema.next_migration
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ require 'helper'
2
+
3
+ module Monark
4
+
5
+ def teardown
6
+ Object.send(:remove_const, :Rails) rescue NameError
7
+ ENV.delete 'RACK_ENV'
8
+ ENV.delete 'MONARK_ENV'
9
+ end
10
+
11
+ test 'should have a version' do
12
+ assert_not_nil Monark::VERSION
13
+ end
14
+
15
+ test "should load env from ENV['MONARK_ENV'] if present" do
16
+ ENV['MONARK_ENV'] = 'production'
17
+ assert_equal 'production', Monark.env
18
+ end
19
+
20
+ test 'should load env from Rails.env if present' do
21
+ ::Rails = OpenStruct.new(:env => 'production')
22
+ assert_equal 'production', Monark.env
23
+ end
24
+
25
+ test "should load env from ENV['RACK_ENV'] if present" do
26
+ ENV['RACK_ENV'] = 'production'
27
+ assert_equal 'production', Monark.env
28
+ end
29
+
30
+ test 'env should default to development' do
31
+ assert_equal 'development', Monark.env
32
+ end
33
+
34
+ test 'should favor MONARK_ENV over Rails env' do
35
+ ::Rails = OpenStruct.new(:env => "test")
36
+ ENV['MONARK_ENV'] = 'production'
37
+ assert_equal 'production', Monark.env
38
+ ENV.delete 'MONARK_ENV'
39
+ assert_equal 'test', Monark.env
40
+ end
41
+
42
+ test 'should favor Rails env over RACK_ENV' do
43
+ ::Rails = OpenStruct.new(:env => "test")
44
+ ENV['RACK_ENV'] = 'production'
45
+ assert_equal 'test', Monark.env
46
+ Object.send :remove_const, :Rails
47
+ assert_equal 'production', Monark.env
48
+ end
49
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: monark
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Norman Clarke
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ none: false
21
+ name: activerecord
22
+ type: :runtime
23
+ prerelease: false
24
+ requirement: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ! '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ none: false
30
+ - !ruby/object:Gem::Dependency
31
+ version_requirements: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ none: false
37
+ name: sqlite3
38
+ type: :development
39
+ prerelease: false
40
+ requirement: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ none: false
46
+ - !ruby/object:Gem::Dependency
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ~>
50
+ - !ruby/object:Gem::Version
51
+ version: '1.3'
52
+ none: false
53
+ name: bundler
54
+ type: :development
55
+ prerelease: false
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: '1.3'
61
+ none: false
62
+ - !ruby/object:Gem::Dependency
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ none: false
69
+ name: rake
70
+ type: :development
71
+ prerelease: false
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ none: false
78
+ - !ruby/object:Gem::Dependency
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ none: false
85
+ name: minitest
86
+ type: :development
87
+ prerelease: false
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ none: false
94
+ description: A simple migrator/seeder
95
+ email:
96
+ - norman@njclarke.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - .gitignore
102
+ - Changelog.md
103
+ - Gemfile
104
+ - LICENSE.txt
105
+ - README.md
106
+ - Rakefile
107
+ - lib/generators/monark_generator.rb
108
+ - lib/generators/templates/Migrations.rb
109
+ - lib/monark.rb
110
+ - lib/monark/context.rb
111
+ - lib/monark/dsl.rb
112
+ - lib/monark/migration.rb
113
+ - lib/monark/railtie.rb
114
+ - lib/monark/schema.rb
115
+ - lib/monark/tasks.rake
116
+ - lib/monark/version.rb
117
+ - monark.gemspec
118
+ - test/fixtures/Migrations.rb
119
+ - test/fixtures/bar.sql.erb
120
+ - test/fixtures/baz.rb
121
+ - test/fixtures/foo.sql
122
+ - test/helper.rb
123
+ - test/monark/context_test.rb
124
+ - test/monark/dsl_test.rb
125
+ - test/monark/migration_test.rb
126
+ - test/monark/schema_test.rb
127
+ - test/monark_test.rb
128
+ homepage: https://github.com/flexminder/monark
129
+ licenses:
130
+ - MIT
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ none: false
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ none: false
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 1.8.23
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: A simple migrator/seeder
153
+ test_files:
154
+ - test/fixtures/Migrations.rb
155
+ - test/fixtures/bar.sql.erb
156
+ - test/fixtures/baz.rb
157
+ - test/fixtures/foo.sql
158
+ - test/helper.rb
159
+ - test/monark/context_test.rb
160
+ - test/monark/dsl_test.rb
161
+ - test/monark/migration_test.rb
162
+ - test/monark/schema_test.rb
163
+ - test/monark_test.rb
164
+ has_rdoc: