mongration 0.0.1.pre.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 449e5a096f4e6f6a0e0dba9e03a6a5377f614ec3
4
+ data.tar.gz: d425dd02caf53a9e61afec6dbb3384d7629758f8
5
+ SHA512:
6
+ metadata.gz: 8ba1932bd58d46878d8c82ffc12fa72fb35149329721cd9729481275b0c95e46698977f4bd7b843f312cb1228d51ec20200dbcc0196dd906198c8519e647d07c
7
+ data.tar.gz: b1ba75f054ab12cfcf498ea544b25bb02ad2948bc0d0c17e63ddbf7ae1a70ede0d72e48f5d27d73b2a1f36ab9012330141235c89df6795e3bc7a96936765915d
data/.gitignore ADDED
@@ -0,0 +1,22 @@
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
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p353
data/.tailor ADDED
@@ -0,0 +1,141 @@
1
+ #------------------------------------------------------------------------------
2
+ # Horizontal Whitespace
3
+ #------------------------------------------------------------------------------
4
+ # allow_hard_tabs True to let hard tabs be considered a single space.
5
+ # Default: false
6
+ #
7
+ # allow_trailing_line_spaces
8
+ # True to skip detecting extra spaces at the ends of
9
+ # lines.
10
+ # Default: false
11
+ #
12
+ # indentation_spaces The number of spaces to consider a proper indent.
13
+ # Default: 2
14
+ #
15
+ # Option: line_continuations
16
+ # Indicates that a statement that spans multiple lines
17
+ # should indent the second and subsequent lines. Ex.:
18
+ # style.indentation_spaces 2, level: :error, line_continuations: true
19
+ #
20
+ # Option: argument_align
21
+ # Allowing you to specify that method declarations and
22
+ # calls should indent to the first argument on
23
+ # subsequent lines. Ex.:
24
+ # style.indentation_spaces 2, level: :error, argument_alignment: true
25
+ #
26
+ # max_line_length The maximum number of characters in a line before
27
+ # tailor complains.
28
+ # Default: 80
29
+ # spaces_after_comma Number of spaces to expect after a comma.
30
+ # Default: 1
31
+ #
32
+ # spaces_before_comma Number of spaces to expect before a comma.
33
+ # Default: 0
34
+ #
35
+ # spaces_after_lbrace The number of spaces to expect after an lbrace ('{').
36
+ # Default: 1
37
+ #
38
+ # spaces_before_lbrace The number of spaces to expect before an lbrace ('{').
39
+ # Default: 1
40
+ #
41
+ # spaces_before_rbrace The number of spaces to expect before an rbrace ('}').
42
+ # Default: 1
43
+ #
44
+ # spaces_in_empty_braces The number of spaces to expect between braces when
45
+ # there's nothing in the braces (i.e. {}).
46
+ # Default: 0
47
+ #
48
+ # spaces_after_lbracket The number of spaces to expect after an
49
+ # lbracket ('[').
50
+ # Default: 0
51
+ #
52
+ # spaces_before_rbracket The number of spaces to expect before an
53
+ # rbracket (']').
54
+ # Default: 0
55
+ #
56
+ # spaces_after_lparen The number of spaces to expect after an
57
+ # lparen ('(').
58
+ # Default: 0
59
+ #
60
+ # spaces_before_rparen The number of spaces to expect before an
61
+ # rbracket (')').
62
+ # Default: 0
63
+ #
64
+ #------------------------------------------------------------------------------
65
+ # Naming
66
+ #------------------------------------------------------------------------------
67
+ # allow_camel_case_methods
68
+ # Setting to true skips detection of camel-case method
69
+ # names (i.e. def myMethod).
70
+ # Default: false
71
+ #
72
+ # allow_screaming_snake_case_classes
73
+ # Setting to true skips detection of screaming
74
+ # snake-case class names (i.e. My_Class).
75
+ # Default: false
76
+ #
77
+ #------------------------------------------------------------------------------
78
+ # Vertical Whitespace
79
+ #------------------------------------------------------------------------------
80
+ # max_code_lines_in_class The number of lines of code in a class to allow before
81
+ # tailor will warn you.
82
+ # Default: 300
83
+ #
84
+ # max_code_lines_in_method
85
+ # The number of lines of code in a method to allow
86
+ # before tailor will warn you.
87
+ # Default: 30
88
+ #
89
+ # trailing_newlines The number of newlines that should be at the end of
90
+ # the file.
91
+ # Default: 1
92
+ #
93
+ #------------------------------------------------------------------------------
94
+ # Common Syntax
95
+ #------------------------------------------------------------------------------
96
+ # allow_conditional_parentheses
97
+ # Checks to see if a conditional is unnecessarily
98
+ # wrapped in parentheses.
99
+ # Default: true
100
+ #
101
+ # allow_unnecessary_double_quotes
102
+ # Checks for use of double-quotes when no interpolation
103
+ # is used.
104
+ # Default: false
105
+ #
106
+ # allow_unnecessary_interpolation
107
+ # Checks for unnecessary interpolation in strings.
108
+ # Default: false
109
+ #
110
+ Tailor.config do |config|
111
+ config.formatters "text"
112
+
113
+ styles = ->(style) do
114
+ style.allow_camel_case_methods false, level: :error
115
+ style.allow_conditional_parentheses false, level: :warn
116
+ style.allow_hard_tabs false, level: :error
117
+ style.allow_screaming_snake_case_classes false, level: :error
118
+ style.allow_trailing_line_spaces false, level: :error
119
+ style.allow_unnecessary_interpolation false, level: :warn
120
+ style.allow_unnecessary_double_quotes false, level: :warn
121
+ style.allow_invalid_ruby false, level: :warn
122
+ style.indentation_spaces 2, level: :off
123
+ style.max_code_lines_in_class 300, level: :error
124
+ style.max_code_lines_in_method 30, level: :error
125
+ style.max_line_length 80, level: :off
126
+ style.spaces_after_comma 1, level: :error
127
+ style.spaces_after_conditional 1, level: :error
128
+ style.spaces_after_lbrace 1, level: :error
129
+ style.spaces_after_lbracket 0, level: :error
130
+ style.spaces_after_lparen 0, level: :error
131
+ style.spaces_before_comma 0, level: :error
132
+ style.spaces_before_lbrace 1, level: :error
133
+ style.spaces_before_rbrace 1, level: :error
134
+ style.spaces_before_rbracket 0, level: :error
135
+ style.spaces_before_rparen 0, level: :error
136
+ style.spaces_in_empty_braces 0, level: :error
137
+ style.trailing_newlines 1, level: :error
138
+ end
139
+
140
+ config.recursive_file_set '*.rb', &styles
141
+ end
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.0.0
5
+ - 1.9.3
6
+ - jruby-19mode
7
+ services:
8
+ - mongodb
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'byebug'
4
+ require 'byebug'
5
+
6
+ gem 'rspec-legacy_formatters'
7
+ gem 'rspec-nc'
8
+
9
+ gem 'guard-rspec', '4.3.1', require: false
10
+
11
+ gem 'rantly', github: 'hayeah/rantly'
12
+
13
+ # Specify your gem's dependencies in mongration.gemspec
14
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 mdalton
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # Mongration [![Build Status](https://travis-ci.org/kcdragon/mongration.svg?branch=master)](https://travis-ci.org/kcdragon/mongration) [![Code Climate](https://codeclimate.com/github/kcdragon/mongration/badges/gpa.svg)](https://codeclimate.com/github/kcdragon/mongration)
2
+
3
+ **ActiveRecord-like Migrations for Mongoid**
4
+
5
+ Mongration is a tool for migrating data. It is designed to have the same interface as [ActiveRecord](https://github.com/rails/rails/tree/master/activerecord)'s migrations but be used with [Mongoid](https://github.com/mongoid/mongoid) instead of an SQL database.
6
+
7
+ Currently, there are only two supported Rake tasks, `db:migrate` and `db:migrate:rollback`. There is a third rake task, `db:migrate:create` which takes the place of the `rails generate migration` generator.
8
+
9
+ ## Support
10
+
11
+ The following versions of Ruby are supported:
12
+
13
+ * MRI 2.1
14
+ * MRI 2.0
15
+ * MRI 1.9.3
16
+ * JRuby 1.9
17
+
18
+ ## Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ gem 'mongration'
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ Or install it yourself as:
29
+
30
+ $ gem install mongration
31
+
32
+ ## Usage
33
+
34
+ The primary usage will be through the Rake tasks `db:migrate` and `db:migrate:rollback`. Migrate will run all migrations that have not been run before. Rollback will rollback the previous migration.
35
+
36
+ Migration files have the following structure:
37
+
38
+ class AddFoo
39
+ def self.up
40
+ end
41
+
42
+ def self.down
43
+ end
44
+ end
45
+
46
+ The above file could be created with `bundle exec rake db:migrate:create[AddFoo]` or `bundle exec rake db:migrate:create[add_foo]`.
47
+
48
+ ## Contributing
49
+
50
+ Contributions are welcome. Please make sure you write a test for any new features or bugs.
51
+
52
+ 1. Fork it ( https://github.com/[my-github-username]/mongration/fork )
53
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
54
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
55
+ 4. Push to the branch (`git push origin my-new-feature`)
56
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.verbose = false
6
+ end
7
+
8
+ require 'tailor/rake_task'
9
+ Tailor::RakeTask.new
10
+
11
+ task :default => [:spec, :tailor]
data/lib/mongration.rb ADDED
@@ -0,0 +1,97 @@
1
+ require 'mongration/version'
2
+
3
+ require 'mongration/errors'
4
+
5
+ require 'mongration/configuration'
6
+ require 'mongration/file'
7
+ require 'mongration/migration'
8
+ require 'mongration/migration_file_writer'
9
+ require 'mongration/null_migration'
10
+ require 'mongration/rake_task'
11
+
12
+ require 'mongration/data_store/base_store'
13
+ require 'mongration/data_store/mongoid/store'
14
+ require 'mongration/data_store/in_memory/store'
15
+
16
+ module Mongration
17
+ extend self
18
+
19
+ def migrate
20
+ file_names = Mongration::File.all.map(&:file_name) - data_store.migrations.flat_map(&:file_names)
21
+
22
+ migration = if file_names.present?
23
+ data_store.build_migration(
24
+ latest_migration.version + 1,
25
+ file_names
26
+ )
27
+ else
28
+ NullMigration.new
29
+ end
30
+
31
+ Migration.new(migration).up
32
+ migration.save
33
+ end
34
+
35
+ def rollback
36
+ migration = latest_migration
37
+ Migration.new(migration).down
38
+ migration.destroy
39
+ end
40
+
41
+ def create_migration(name, options = {})
42
+ snakecase = name.gsub(/([a-z])([A-Z0-9])/, '\1_\2').downcase
43
+ file_name = "#{next_migration_number}_#{snakecase}.rb"
44
+ MigrationFileWriter.write(file_name, { dir: dir }.merge(options))
45
+ end
46
+
47
+ def configure
48
+ yield configuration if block_given?
49
+ end
50
+
51
+ private
52
+
53
+ def next_migration_number
54
+ if timestamps?
55
+ Time.now.utc.strftime('%Y%m%d%H%M%S').to_i
56
+ else
57
+ latest_file = Mongration::File.latest
58
+
59
+ number = if latest_file
60
+ latest_file.number + 1
61
+ else
62
+ 1
63
+ end
64
+ '%.3d' % number
65
+ end
66
+ end
67
+
68
+ def latest_migration
69
+ data_store.migrations.max_by(&:version) || NullMigration.new
70
+ end
71
+
72
+ def configuration
73
+ @configuration ||= Configuration.new
74
+ end
75
+
76
+ def method_missing(method, *args)
77
+ if configuration.respond_to?(method, *args)
78
+ configuration.send(method, *args)
79
+ else
80
+ super
81
+ end
82
+ end
83
+
84
+ def respond_to?(method, *args)
85
+ super || configuration.respond_to?(method, *args)
86
+ end
87
+ end
88
+
89
+ Mongration.configure do |config|
90
+ config.dir = ::File.join('db', 'migrate')
91
+ config.timestamps = true
92
+
93
+ begin
94
+ config.data_store = Mongration::DataStore::Mongoid::Store.new
95
+ rescue Mongration::DataStore::Mongoid::ConfigNotFound
96
+ end
97
+ end
@@ -0,0 +1,31 @@
1
+ module Mongration
2
+
3
+ # @private
4
+ class Configuration
5
+ attr_reader :dir
6
+ attr_writer :err_out
7
+ attr_accessor :data_store, :timestamps
8
+
9
+ def dir=(dir)
10
+ unless ::File.exists?(dir)
11
+ print_warning("Migration Directory #{dir} does not exists.")
12
+ end
13
+
14
+ @dir = dir
15
+ end
16
+
17
+ def timestamps?
18
+ @timestamps
19
+ end
20
+
21
+ private
22
+
23
+ def print_warning(message)
24
+ err_out.puts("Warning: #{message}")
25
+ end
26
+
27
+ def err_out
28
+ @err_out || $stderr
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ module Mongration
2
+ module DataStore
3
+ module InMemory
4
+ class Store
5
+ include BaseStore
6
+
7
+ class Migration < Struct.new(:version, :file_names)
8
+ attr_reader :destroyed
9
+
10
+ def save; end
11
+
12
+ def destroy
13
+ @destroyed = true
14
+ end
15
+ end
16
+
17
+ def initialize
18
+ @migrations = []
19
+ end
20
+
21
+ def migrations
22
+ @migrations.reject(&:destroyed)
23
+ end
24
+
25
+ def build_migration(version, file_names)
26
+ migration = Migration.new(version, file_names)
27
+ @migrations << migration
28
+ migration
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ module Mongration
2
+ module DataStore
3
+ module Mongoid
4
+
5
+ # @private
6
+ class Migration
7
+ include ::Mongoid::Document
8
+
9
+ field :version, type: Integer
10
+ field :file_names, type: Array
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,54 @@
1
+ require 'mongoid'
2
+
3
+ require 'mongration/data_store/mongoid/migration'
4
+
5
+ module Mongration
6
+ module DataStore
7
+ module Mongoid
8
+ class Store
9
+ include BaseStore
10
+
11
+ class Mongration::DataStore::Mongoid::ConfigNotFound < ::Mongration::Errors
12
+ def initialize(path)
13
+ super("#{path} cannot be found.")
14
+ end
15
+ end
16
+
17
+ DEFAULT_CONFIG_PATH = ::File.join('config', 'mongoid.yml')
18
+
19
+ # @params [Hash] options
20
+ #
21
+ def initialize(options = {})
22
+ @config_path = options[:config_path] || DEFAULT_CONFIG_PATH
23
+
24
+ load_configuration
25
+ end
26
+
27
+ # @private
28
+ def migrations
29
+ Migration.all
30
+ end
31
+
32
+ # @private
33
+ def build_migration(version, file_names)
34
+ Migration.new(version: version, file_names: file_names)
35
+ end
36
+
37
+ private
38
+
39
+ def load_configuration
40
+ unless ::File.exists?(@config_path)
41
+ raise Mongration::DataStore::Mongoid::ConfigNotFound.new(@config_path)
42
+ end
43
+
44
+ env = if defined?(Rails)
45
+ Rails.env
46
+ else
47
+ :test
48
+ end
49
+ ::Mongoid.load!(@config_path, env)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,3 @@
1
+ module Mongration
2
+ class Errors < StandardError; end
3
+ end
@@ -0,0 +1,59 @@
1
+ module Mongration
2
+
3
+ # @private
4
+ class File
5
+ include Comparable
6
+
7
+ def self.all
8
+ Dir[::File.join(Mongration.dir, '*.rb')].map do |path|
9
+ path.pathmap('%f')
10
+ end.map { |file_name| new(file_name) }
11
+ end
12
+
13
+ def self.latest
14
+ all.max
15
+ end
16
+
17
+ attr_reader :file_name
18
+
19
+ def initialize(file_name)
20
+ @file_name = file_name
21
+ end
22
+
23
+ def up
24
+ load_file
25
+ klass.up
26
+ end
27
+
28
+ def down
29
+ load_file
30
+ klass.down
31
+ end
32
+
33
+ def number
34
+ @file_name.split('_').first.to_i
35
+ end
36
+
37
+ def <=>(other)
38
+ number <=> other.number
39
+ end
40
+
41
+ def class_name
42
+ @file_name.chomp('.rb').gsub(/^\d+_/, '').camelize
43
+ end
44
+
45
+ private
46
+
47
+ def load_file
48
+ load(::File.join(Dir.pwd, dir, @file_name))
49
+ end
50
+
51
+ def dir
52
+ Mongration.dir
53
+ end
54
+
55
+ def klass
56
+ class_name.constantize
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,25 @@
1
+ module Mongration
2
+
3
+ # @private
4
+ class Migration
5
+ def initialize(migration)
6
+ @migration = migration
7
+ end
8
+
9
+ def up
10
+ files.sort.each(&:up)
11
+ end
12
+
13
+ def down
14
+ files.sort.reverse.each(&:down)
15
+ end
16
+
17
+ private
18
+
19
+ def files
20
+ @migration.file_names.map do |file_name|
21
+ Mongration::File.new(file_name)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,40 @@
1
+ module Mongration
2
+
3
+ # @private
4
+ class MigrationFileWriter
5
+
6
+ def self.write(file_name, options = {})
7
+ new(file_name, options).write
8
+ end
9
+
10
+ def initialize(file_name, options = {})
11
+ @file_name = file_name
12
+ @dir = options[:dir]
13
+ @up = options[:up]
14
+ @down = options[:down]
15
+ end
16
+
17
+ def write
18
+ ::File.open(::File.join(@dir, @file_name), 'w') do |file|
19
+ file.write(<<EOS
20
+ class #{class_name}
21
+ def self.up
22
+ #{@up}
23
+ end
24
+
25
+ def self.down
26
+ #{@down}
27
+ end
28
+ end
29
+ EOS
30
+ )
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def class_name
37
+ Mongration::File.new(@file_name).class_name
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+ module Mongration
2
+
3
+ # @private
4
+ class NullMigration
5
+ def version
6
+ 0
7
+ end
8
+
9
+ def file_names
10
+ []
11
+ end
12
+
13
+ def save; end
14
+ def destroy; end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ require 'rake'
2
+
3
+ namespace :db do
4
+ task :migrate do
5
+ Mongration.migrate
6
+ end
7
+
8
+ namespace :migrate do
9
+ task :rollback do
10
+ Mongration.rollback
11
+ end
12
+
13
+ task :create, [:name] do |t, args|
14
+ name = args[:name]
15
+ Mongration.create_migration(name)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Mongration
2
+ VERSION = '0.0.1-alpha'
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mongration/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mongration"
8
+ spec.version = Mongration::VERSION
9
+ spec.authors = ["Mike Dalton"]
10
+ spec.email = ["michaelcdalton@gmail.com"]
11
+ spec.summary = %q{Migrations for Mongoid}
12
+ spec.description = %q{Mongration is a tool for migrating data. It is designed to have the same interface as ActiveRecord's migrations but be used with Mongoid instead of a SQL database.}
13
+ spec.homepage = "https://github.com/kcdragon/mongration"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "mongoid", ">= 3.0"
22
+ spec.add_dependency "rake"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rspec", "= 3.0"
26
+ spec.add_development_dependency "tailor", "= 1.4.0"
27
+ spec.add_development_dependency "timecop", "= 0.7.1"
28
+ end
@@ -0,0 +1,6 @@
1
+ test:
2
+ sessions:
3
+ default:
4
+ database: mongration
5
+ hosts:
6
+ - localhost:27017
File without changes
@@ -0,0 +1,70 @@
1
+ module IntegrationFixtures
2
+ def create(file_name, up, down)
3
+ Mongration::MigrationFileWriter.
4
+ write(file_name, up: up, down: down, dir: Mongration.dir)
5
+ end
6
+
7
+ def foo_create_migration
8
+ create(
9
+ '001_add_foo.rb',
10
+ 'Foo.instances << Foo.new',
11
+ 'Foo.instances.pop'
12
+ )
13
+ end
14
+
15
+ def bar_create_migration
16
+ create(
17
+ '002_add_bar.rb',
18
+ 'Bar.instances << Bar.new',
19
+ 'Bar.instances.pop'
20
+ )
21
+ end
22
+
23
+ def foo_update_migration
24
+ create(
25
+ '0003_add_name_to_foo.rb',
26
+ 'foo = Foo.instances.first; foo.name = "Test"',
27
+ 'foo = Foo.instances.first; foo.name = ""'
28
+ )
29
+ end
30
+
31
+ def bar_update_migration
32
+ create(
33
+ '004_add_name_to_bar.rb',
34
+ 'bar = Bar.instances.first; bar.name = "Test"',
35
+ 'bar = Bar.instances.first; bar.name = ""'
36
+ )
37
+ end
38
+ end
39
+
40
+ class Foo
41
+ class << self
42
+ attr_accessor :instances
43
+
44
+ def count
45
+ instances.count
46
+ end
47
+ end
48
+
49
+ self.instances = []
50
+
51
+ attr_accessor :name
52
+ end
53
+
54
+ class Bar
55
+ class << self
56
+ attr_accessor :instances
57
+
58
+ def count
59
+ instances.count
60
+ end
61
+ end
62
+
63
+ self.instances = []
64
+
65
+ attr_accessor :name
66
+ end
67
+
68
+ RSpec.configure do |config|
69
+ config.include(IntegrationFixtures)
70
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongration do
4
+
5
+ it 'runs a single migration' do
6
+ foo_create_migration
7
+
8
+ Mongration.migrate
9
+
10
+ expect(Foo.count).to eq(1)
11
+ end
12
+
13
+ it 'skips the first migration and runs a second migration' do
14
+ foo_create_migration
15
+ Mongration.migrate
16
+
17
+ bar_create_migration
18
+ Mongration.migrate
19
+
20
+ expect(Foo.count).to eq(1)
21
+ expect(Bar.count).to eq(1)
22
+ end
23
+
24
+ it 'rollsback a migration' do
25
+ foo_create_migration
26
+ Mongration.migrate
27
+
28
+ Mongration.rollback
29
+ expect(Foo.count).to eq(0)
30
+ end
31
+
32
+ it 'can rollback twice' do
33
+ foo_create_migration
34
+ Mongration.migrate
35
+
36
+ bar_create_migration
37
+ Mongration.migrate
38
+
39
+ Mongration.rollback
40
+ expect(Foo.count).to eq(1)
41
+
42
+ Mongration.rollback
43
+ expect(Foo.count).to eq(0)
44
+ end
45
+
46
+ it 'does not rollback when there are no migrations' do
47
+ Foo.instances << Foo.new
48
+ Mongration.rollback
49
+ expect(Foo.count).to eq(1)
50
+ end
51
+
52
+ it 'does not migrate when there are no migrations' do
53
+ foo_create_migration
54
+ Mongration.migrate
55
+ Mongration.migrate
56
+ expect(Foo.count).to eq(1)
57
+ end
58
+
59
+ it 'migrates files in order' do
60
+ foo_update_migration
61
+ foo_create_migration
62
+ Mongration.migrate
63
+
64
+ foo = Foo.instances.first
65
+ expect(foo.name).to eq('Test')
66
+ end
67
+
68
+ it 'rollbacks files in order' do
69
+ bar_create_migration
70
+ bar_update_migration
71
+ Mongration.migrate
72
+ Mongration.rollback
73
+
74
+ expect(Bar.count).to eq(0)
75
+ end
76
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongration do
4
+
5
+ it 'creates number-based template with CamelCase file name' do
6
+ Mongration.create_migration('AddFoo')
7
+
8
+ migration_file_name = File.join('spec', 'db', 'migrate', '001_add_foo.rb')
9
+ expect(File.exists?(migration_file_name)).to eq(true)
10
+ end
11
+
12
+ it 'creates number-based template with snake_case file name' do
13
+ Mongration.create_migration('add_foo')
14
+
15
+ migration_file_name = File.join('spec', 'db', 'migrate', '001_add_foo.rb')
16
+ expect(File.exists?(migration_file_name)).to eq(true)
17
+ end
18
+
19
+ it 'creates time-based template' do
20
+ Mongration.configure do |config|
21
+ config.timestamps = true
22
+ end
23
+
24
+ Timecop.freeze(Time.utc(2014, 1, 1, 1, 1, 1)) do
25
+ Mongration.create_migration('add_foo')
26
+ end
27
+
28
+ migration_file_name = File.join('spec', 'db', 'migrate', '20140101010101_add_foo.rb')
29
+ expect(File.exists?(migration_file_name)).to eq(true)
30
+ end
31
+
32
+ it 'increments migration number' do
33
+ Mongration.create_migration('add_foo')
34
+ Mongration.migrate
35
+ Mongration.create_migration('add_bar')
36
+
37
+ migration_file_name = File.join('spec', 'db', 'migrate', '002_add_bar.rb')
38
+ expect(File.exists?(migration_file_name)).to eq(true)
39
+ end
40
+
41
+ it 'includes non-migrated files when determining migration number' do
42
+ Mongration.create_migration('add_foo')
43
+ Mongration.create_migration('add_bar')
44
+
45
+ migration_file_name = File.join('spec', 'db', 'migrate', '002_add_bar.rb')
46
+ expect(File.exists?(migration_file_name)).to eq(true)
47
+ end
48
+
49
+ it 'creates file with migration class' do
50
+ Mongration.create_migration('add_foo', up: 'puts "up"', down: 'puts "down"')
51
+
52
+ migration_file_name = File.join('spec', 'db', 'migrate', '001_add_foo.rb')
53
+ contents = File.open(migration_file_name) do |file|
54
+ file.read
55
+ end
56
+
57
+ expect(contents).to eq(<<EOS
58
+ class AddFoo
59
+ def self.up
60
+ puts "up"
61
+ end
62
+
63
+ def self.down
64
+ puts "down"
65
+ end
66
+ end
67
+ EOS
68
+ )
69
+ end
70
+ end
@@ -0,0 +1,88 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'rantly/rspec_extensions'
5
+
6
+ require 'mongration'
7
+ Mongration.configure do |config|
8
+ config.data_store = Mongration::DataStore::Mongoid::Store.new(config_path: File.join('spec', 'config', 'mongoid.yml'))
9
+ end
10
+
11
+ Dir[File.join(Dir.pwd, 'spec', 'support', '*.rb')].each { |f| require f }
12
+ Dir[File.join(Dir.pwd, 'spec', 'fixtures', '*.rb')].each { |f| require f }
13
+
14
+ require 'timecop'
15
+ Timecop.safe_mode = true
16
+
17
+ RSpec.configure do |config|
18
+
19
+ # These two settings work together to allow you to limit a spec run
20
+ # to individual examples or groups you care about by tagging them with
21
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
22
+ # get run.
23
+ config.filter_run :focus
24
+ config.run_all_when_everything_filtered = true
25
+
26
+ # Many RSpec users commonly either run the entire suite or an individual
27
+ # file, and it's useful to allow more verbose output when running an
28
+ # individual spec file.
29
+ if config.files_to_run.one?
30
+ # Use the documentation formatter for detailed output,
31
+ # unless a formatter has already been configured
32
+ # (e.g. via a command-line flag).
33
+ config.default_formatter = 'doc'
34
+ end
35
+
36
+ # Run specs in random order to surface order dependencies. If you find an
37
+ # order dependency and want to debug it, you can fix the order by providing
38
+ # the seed, which is printed after each run.
39
+ # --seed 1234
40
+ config.order = :random
41
+
42
+ # Seed global randomization in this process using the `--seed` CLI option.
43
+ # Setting this allows you to use `--seed` to deterministically reproduce
44
+ # test failures related to randomization by passing the same `--seed` value
45
+ # as the one that triggered the failure.
46
+ Kernel.srand config.seed
47
+
48
+ # rspec-expectations config goes here. You can use an alternate
49
+ # assertion/expectation library such as wrong or the stdlib/minitest
50
+ # assertions if you prefer.
51
+ config.expect_with :rspec do |expectations|
52
+ # Enable only the newer, non-monkey-patching expect syntax.
53
+ # For more details, see:
54
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
55
+ expectations.syntax = :expect
56
+ end
57
+
58
+ # rspec-mocks config goes here. You can use an alternate test double
59
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
60
+ config.mock_with :rspec do |mocks|
61
+ # Enable only the newer, non-monkey-patching expect syntax.
62
+ # For more details, see:
63
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
64
+ mocks.syntax = :expect
65
+
66
+ # Prevents you from mocking or stubbing a method that does not exist on
67
+ # a real object. This is generally recommended.
68
+ mocks.verify_partial_doubles = true
69
+ end
70
+
71
+ config.before(:each) do
72
+
73
+ # clear out migration files created
74
+ dir = File.join('spec', 'db', 'migrate')
75
+ Mongration.configure do |config|
76
+ config.dir = dir
77
+ config.timestamps = false
78
+ end
79
+ Dir.glob(File.join(dir, '*')).each { |f| File.delete(f) }
80
+
81
+ # clear out database
82
+ Mongoid.purge!
83
+
84
+ # clear out models
85
+ Foo.instances = []
86
+ Bar.instances = []
87
+ end
88
+ end
@@ -0,0 +1,18 @@
1
+ shared_examples_for 'store interface' do
2
+ it 'adds a migration' do
3
+ migration = store.build_migration(1, ['001_foo.rb'])
4
+ migration.save
5
+
6
+ migration = store.migrations.first
7
+ expect(migration.version).to eq(1)
8
+ expect(migration.file_names).to eq(['001_foo.rb'])
9
+ end
10
+
11
+ it 'destroys a migration' do
12
+ migration = store.build_migration(1, ['001_foo.rb'])
13
+ migration.save
14
+ migration.destroy
15
+
16
+ expect(store.migrations).to eq([])
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongration::DataStore::InMemory::Store do
4
+
5
+ it_behaves_like 'store interface' do
6
+ let(:store) do
7
+ Mongration::DataStore::InMemory::Store.new
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongration::DataStore::Mongoid::Store do
4
+
5
+ it_behaves_like 'store interface' do
6
+ let(:store) do
7
+ Mongration::DataStore::Mongoid::Store.new(
8
+ config_path: 'spec/config/mongoid.yml'
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongration::File do
4
+
5
+ describe 'comparable' do
6
+ it 'sorts by number' do
7
+ second = Mongration::File.new('002_a.rb')
8
+ first = Mongration::File.new('001_b.rb')
9
+
10
+ expect([second, first].sort).to eq([first, second])
11
+ end
12
+
13
+ it 'sorts by timestamp' do
14
+ second = Mongration::File.new('20140825115042_a.rb')
15
+ first = Mongration::File.new('20140825115026_b.rb')
16
+
17
+ expect([second, first].sort).to eq([first, second])
18
+ end
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongration
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.pre.alpha
5
+ platform: ruby
6
+ authors:
7
+ - Mike Dalton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mongoid
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: tailor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 1.4.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.4.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: timecop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 0.7.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 0.7.1
97
+ description: Mongration is a tool for migrating data. It is designed to have the same
98
+ interface as ActiveRecord's migrations but be used with Mongoid instead of a SQL
99
+ database.
100
+ email:
101
+ - michaelcdalton@gmail.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - .gitignore
107
+ - .rspec
108
+ - .ruby-version
109
+ - .tailor
110
+ - .travis.yml
111
+ - Gemfile
112
+ - LICENSE.txt
113
+ - README.md
114
+ - Rakefile
115
+ - lib/mongration.rb
116
+ - lib/mongration/configuration.rb
117
+ - lib/mongration/data_store/in_memory/store.rb
118
+ - lib/mongration/data_store/mongoid/migration.rb
119
+ - lib/mongration/data_store/mongoid/store.rb
120
+ - lib/mongration/errors.rb
121
+ - lib/mongration/file.rb
122
+ - lib/mongration/migration.rb
123
+ - lib/mongration/migration_file_writer.rb
124
+ - lib/mongration/null_migration.rb
125
+ - lib/mongration/rake_task.rb
126
+ - lib/mongration/version.rb
127
+ - mongration.gemspec
128
+ - spec/config/mongoid.yml
129
+ - spec/db/migrate/.gitkeep
130
+ - spec/fixtures/integration.rb
131
+ - spec/integration/mongration_spec.rb
132
+ - spec/integration/template_spec.rb
133
+ - spec/spec_helper.rb
134
+ - spec/support/store_interface.rb
135
+ - spec/unit/mongration/data_store/in_memory/store_spec.rb
136
+ - spec/unit/mongration/data_store/mongoid/store_spec.rb
137
+ - spec/unit/mongration/file_spec.rb
138
+ homepage: https://github.com/kcdragon/mongration
139
+ licenses:
140
+ - MIT
141
+ metadata: {}
142
+ post_install_message:
143
+ rdoc_options: []
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - '>='
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - '>'
154
+ - !ruby/object:Gem::Version
155
+ version: 1.3.1
156
+ requirements: []
157
+ rubyforge_project:
158
+ rubygems_version: 2.2.2
159
+ signing_key:
160
+ specification_version: 4
161
+ summary: Migrations for Mongoid
162
+ test_files:
163
+ - spec/config/mongoid.yml
164
+ - spec/db/migrate/.gitkeep
165
+ - spec/fixtures/integration.rb
166
+ - spec/integration/mongration_spec.rb
167
+ - spec/integration/template_spec.rb
168
+ - spec/spec_helper.rb
169
+ - spec/support/store_interface.rb
170
+ - spec/unit/mongration/data_store/in_memory/store_spec.rb
171
+ - spec/unit/mongration/data_store/mongoid/store_spec.rb
172
+ - spec/unit/mongration/file_spec.rb
173
+ has_rdoc: