maglevrecord 0.1.1 → 0.1.2
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.
- data/.gitignore +7 -0
- data/.travis.yml +0 -1
- data/README.md +22 -7
- data/Rakefile +2 -2
- data/install.sh +0 -1
- data/lib/maglev_record/base.rb +10 -1
- data/lib/maglev_record/enumerable.rb +6 -1
- data/lib/maglev_record/errors.rb +3 -0
- data/lib/maglev_record/maglev_record.rb +1 -1
- data/lib/maglev_record/maglev_support/concern.rb +2 -3
- data/lib/maglev_record/maglev_support/secure_password.rb +2 -3
- data/lib/maglev_record/migration/loader.rb +1 -1
- data/lib/maglev_record/migration/migration.rb +14 -0
- data/lib/maglev_record/migration/migrator.rb +22 -4
- data/lib/maglev_record/migration/operations.rb +58 -0
- data/lib/maglev_record/persistence.rb +12 -5
- data/lib/maglev_record/read_write.rb +38 -7
- data/lib/maglev_record/rooted_enumerable.rb +6 -1
- data/lib/maglev_record/rooted_persistence.rb +4 -0
- data/lib/maglev_record/sensible.rb +2 -2
- data/lib/maglev_record/snapshot/change.rb +54 -15
- data/lib/maglev_record/snapshot/class_change.rb +66 -0
- data/lib/maglev_record/snapshot/class_snapshot.rb +63 -0
- data/lib/maglev_record/snapshot/snapshot.rb +44 -38
- data/lib/maglev_record/snapshot/snapshotable.rb +81 -26
- data/lib/maglev_record/snapshot/superclass_mismatch_change.rb +143 -0
- data/lib/maglev_record/snapshot.rb +3 -2
- data/lib/maglev_record/validations.rb +49 -0
- data/lib/maglev_record.rb +3 -2
- data/lib/tasks/database.rake +61 -17
- data/test/automigration/rake_task_base.rb +57 -0
- data/test/automigration/test_auto.slow.rb +38 -0
- data/test/automigration/test_migration_string.rb +173 -0
- data/test/automigration/test_rake_task_preconditions.slow.rb +41 -0
- data/test/automigration/test_show.slow.rb +21 -0
- data/test/automigration/test_superclass_mismatch.rb +96 -0
- data/test/example_model.rb +7 -5
- data/test/migration/base_lectures.rb +30 -0
- data/test/migration/operation_setup.rb +66 -56
- data/test/migration/projects/automigration/.gitignore +15 -0
- data/test/migration/projects/automigration/Gemfile +44 -0
- data/test/migration/projects/automigration/Gemfile.lock +115 -0
- data/test/migration/projects/automigration/README.rdoc +261 -0
- data/test/migration/projects/automigration/Rakefile +17 -0
- data/test/migration/projects/automigration/app/assets/images/rails.png +0 -0
- data/test/migration/projects/automigration/app/assets/javascripts/application.js +15 -0
- data/test/migration/projects/automigration/app/assets/stylesheets/application.css +13 -0
- data/test/migration/projects/automigration/app/controllers/application_controller.rb +3 -0
- data/test/migration/projects/automigration/app/helpers/application_helper.rb +2 -0
- data/test/migration/projects/automigration/app/mailers/.gitkeep +0 -0
- data/test/migration/projects/automigration/app/models/.gitkeep +0 -0
- data/test/migration/projects/automigration/app/models/project_model.rb +8 -0
- data/test/migration/projects/automigration/app/views/layouts/application.html.erb +14 -0
- data/test/migration/projects/automigration/config/application.rb +62 -0
- data/test/migration/projects/automigration/config/boot.rb +6 -0
- data/test/migration/projects/automigration/config/database.yml +25 -0
- data/test/migration/projects/automigration/config/environment.rb +5 -0
- data/test/migration/projects/automigration/config/environments/development.rb +37 -0
- data/test/migration/projects/automigration/config/environments/production.rb +67 -0
- data/test/migration/projects/automigration/config/initializers/backtrace_silencers.rb +7 -0
- data/test/migration/projects/automigration/config/initializers/inflections.rb +15 -0
- data/test/migration/projects/automigration/config/initializers/mime_types.rb +5 -0
- data/test/migration/projects/automigration/config/initializers/secret_token.rb +7 -0
- data/test/migration/projects/automigration/config/initializers/session_store.rb +8 -0
- data/test/migration/projects/automigration/config/initializers/wrap_parameters.rb +14 -0
- data/test/migration/projects/automigration/config/locales/en.yml +5 -0
- data/test/migration/projects/automigration/config/routes.rb +58 -0
- data/test/migration/projects/automigration/config.ru +4 -0
- data/test/migration/projects/automigration/db/seeds.rb +7 -0
- data/test/migration/projects/automigration/lib/assets/.gitkeep +0 -0
- data/test/migration/projects/automigration/lib/tasks/.gitkeep +0 -0
- data/test/migration/projects/automigration/log/.gitkeep +0 -0
- data/test/migration/projects/automigration/public/404.html +26 -0
- data/test/migration/projects/automigration/public/422.html +26 -0
- data/test/migration/projects/automigration/public/500.html +25 -0
- data/test/migration/projects/automigration/public/favicon.ico +0 -0
- data/test/migration/projects/automigration/public/index.html +241 -0
- data/test/migration/projects/automigration/public/robots.txt +5 -0
- data/test/migration/projects/automigration/script/rails +6 -0
- data/test/migration/projects/project2/Rakefile +2 -2
- data/test/migration/projects/project2/migrations/migration_2013-04-Apr-23_17.31.38.rb +1 -1
- data/test/migration/projects/project2/migrations/migration_2013-04-Apr-23_17.31.52.rb +1 -1
- data/test/migration/projects/project2/migrations/migration_2013-04-Apr-23_17.32.07.rb +1 -1
- data/test/migration/test_change_superclass.rb +111 -0
- data/test/migration/test_loader.rb +6 -0
- data/test/migration/test_project.rb +1 -29
- data/test/migration/test_project1.slow.rb +1 -0
- data/test/migration/test_project2.slow.rb +7 -0
- data/test/migration/test_remove.rb +123 -2
- data/test/migration/todo.txt +1 -1
- data/test/more_asserts.rb +1 -1
- data/test/snapshot/test_attributes.rb +33 -0
- data/test/snapshot/{test_snapshot_attributes.slow.rb → test_attributes.slow.rb} +3 -5
- data/test/snapshot/test_classes.rb +32 -0
- data/test/snapshot/{test_snapshot_classes.slow.rb → test_classes.slow.rb} +1 -1
- data/test/snapshot/test_from_file_system.rb +113 -0
- data/test/snapshot/test_methods.rb +136 -0
- data/test/snapshot/test_methods.slow.rb +67 -0
- data/test/snapshot/test_reset.rb +68 -0
- data/test/snapshot/test_snapshot.rb +41 -75
- data/test/snapshot/test_snapshot.slow.rb +98 -0
- data/test/snapshot/test_snapshotable.rb +0 -1
- data/test/temp_dir_test.rb +40 -0
- data/test/test_active_model_like_interface.rb +4 -1
- data/test/test_model_timestamps.rb +13 -5
- data/test/test_query_interface.rb +10 -0
- data/test/test_sensibles.rb +18 -10
- data/test/test_validation.rb +2 -12
- metadata +64 -5
@@ -0,0 +1,57 @@
|
|
1
|
+
require "migration/test_project.rb"
|
2
|
+
|
3
|
+
class RakeTaskTestBase < ProjectTest
|
4
|
+
|
5
|
+
def setup
|
6
|
+
Maglev.abort_transaction
|
7
|
+
#Maglev.persistent do
|
8
|
+
# @rooted_book = Object.remove_const :RootedBook if defined? RootedBook
|
9
|
+
#end
|
10
|
+
@project_name = 'automigration'
|
11
|
+
super
|
12
|
+
project_model_source("")
|
13
|
+
Maglev.persistent do
|
14
|
+
Object.remove_const :ProjectModel if defined?(ProjectModel)
|
15
|
+
end
|
16
|
+
snapshot!
|
17
|
+
Maglev.commit_transaction
|
18
|
+
@error_message = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_snapshot
|
22
|
+
# should only snapshot project model
|
23
|
+
classes = MaglevRecord::Snapshotable.snapshotable_classes.select(&:maglev_persistable?)
|
24
|
+
classes -= [BaseLecture1, BaseLecture2] if defined? BaseLecture1
|
25
|
+
MaglevRecord::Snapshot.new classes
|
26
|
+
end
|
27
|
+
|
28
|
+
def snapshot!
|
29
|
+
# define the interface that rake should use
|
30
|
+
Maglev::PERSISTENT_ROOT[:last_snapshot] = new_snapshot
|
31
|
+
end
|
32
|
+
|
33
|
+
def changes
|
34
|
+
new_snapshot.changes_since Maglev::PERSISTENT_ROOT[:last_snapshot]
|
35
|
+
end
|
36
|
+
|
37
|
+
def teardown
|
38
|
+
super
|
39
|
+
puts @error_mesage unless @error_message.nil?
|
40
|
+
Maglev.abort_transaction
|
41
|
+
#Object.const_set :RootedBook, @rooted_book unless @rooted_book.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def project_model_source(string)
|
45
|
+
file_path = "app/models/project_model.rb"
|
46
|
+
File.open(file_path, 'w') { |file| file.write(string)}
|
47
|
+
load file_path
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_no_changes_since
|
51
|
+
assert_equal [], changes.removed_classes
|
52
|
+
assert_equal [], changes.changed_classes
|
53
|
+
assert_equal [], changes.new_classes
|
54
|
+
assert changes.nothing_changed?
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "automigration/rake_task_base"
|
2
|
+
|
3
|
+
class TestAutomigrationShow < RakeTaskTestBase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@output = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
super
|
12
|
+
puts @output unless @output.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_auto
|
16
|
+
project_model_source("class ProjectModel
|
17
|
+
include MaglevRecord::Base
|
18
|
+
def x; end
|
19
|
+
end")
|
20
|
+
@output = rake("migrate:auto")
|
21
|
+
assert File.directory? './migrations'
|
22
|
+
assert_not_equal [], Dir[File.join(FileUtils.pwd, 'migrations', '*')]
|
23
|
+
file_name = Dir['./migrations/*'].first
|
24
|
+
assert_include? @output, file_name
|
25
|
+
content = File.open(file_name){|f| f.read }
|
26
|
+
assert_include? content, "MaglevRecord::Migration.new"
|
27
|
+
assert_include? content, " def up\n #new class: ProjectModel\n end"
|
28
|
+
@output = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_no_changes_no_file
|
32
|
+
@output = rake("migrate:auto")
|
33
|
+
assert_equal "# no changes\n", @output
|
34
|
+
assert_equal [], Dir[File.join(FileUtils.pwd, 'migrations', '*')]
|
35
|
+
@output = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require "snapshot/test_snapshot"
|
2
|
+
|
3
|
+
class MigrationStringTest < FastSnapshotTest
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
Lecture2.attr_accessor :lecturer
|
8
|
+
def Lecture.class_method1;end
|
9
|
+
Lecture.class_eval{def instance_method1;end}
|
10
|
+
snapshot!
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_no_migration_string_if_nothing_happens
|
18
|
+
assert_migration_string ""
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_class_removed
|
22
|
+
remove_class Lecture3
|
23
|
+
assert_migration_string 'delete_class Lecture3'
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_two_classes_removed
|
27
|
+
remove_class Lecture2, Lecture3
|
28
|
+
assert_migration_string "delete_class Lecture2\ndelete_class Lecture3"
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_rename_class_is_remove_and_add
|
32
|
+
remove_class Lecture4
|
33
|
+
snapshot! # Lecture3 exists
|
34
|
+
redefine_migration_classes
|
35
|
+
remove_class Lecture3 # Lecture4 exists, Lecture3 is removed
|
36
|
+
assert_migration_string "rename_class Lecture3, :Lecture4"
|
37
|
+
end
|
38
|
+
|
39
|
+
# TODO string when attributes renamed when class renamed
|
40
|
+
# TODO string when many things happen
|
41
|
+
# TODO lecture -> lectures map to list block
|
42
|
+
|
43
|
+
def test_added_attr_accessor
|
44
|
+
assert_not_include? Lecture3.instance_methods, "test_accessor"
|
45
|
+
Lecture3.attr_accessor :test_accessor
|
46
|
+
assert_migration_string "#new accessor :test_accessor of Lecture3\n" +
|
47
|
+
"#new instance method: Lecture3.new.test_accessor\n" +
|
48
|
+
"#new instance method: Lecture3.new.test_accessor="
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_removed_attr_accessor
|
52
|
+
Lecture2.delete_attribute(:lecturer)
|
53
|
+
assert_migration_string "Lecture2.delete_attribute(:lecturer)"
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_remove_accessor_is_remove_and_add
|
57
|
+
Lecture2.delete_attribute(:lecturer)
|
58
|
+
Lecture2.attr_accessor :testitatetue
|
59
|
+
string = "Lecture2.rename_attribute(:lecturer, :testitatetue)\n"
|
60
|
+
string += "#new instance method: Lecture2.new.testitatetue\n"
|
61
|
+
string += "#new instance method: Lecture2.new.testitatetue="
|
62
|
+
assert_migration_string string
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_add_class_requires_no_migration_string
|
66
|
+
remove_class Lecture3, Lecture4
|
67
|
+
snapshot!
|
68
|
+
redefine_migration_classes
|
69
|
+
migration_string = " #new class: Lecture3\n #new class: Lecture4"
|
70
|
+
assert_migration_string migration_string, 4
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_add_class_method
|
74
|
+
def Lecture.class_method2;end
|
75
|
+
assert_migration_string "#new class method: Lecture.class_method2"
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_add_instance_method
|
79
|
+
Lecture.class_eval{def instance_method2;end}
|
80
|
+
assert_migration_string "#new instance method: Lecture.new.instance_method2"
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_remove_class_method
|
84
|
+
Lecture.singleton_class.remove_method :class_method1
|
85
|
+
assert_migration_string 'Lecture.remove_class_method :class_method1'
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_remove_instance_method
|
89
|
+
Lecture.remove_method :instance_method1
|
90
|
+
assert_migration_string 'Lecture.remove_instance_method :instance_method1'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class AttributeAccessorsMoveTest < FastSnapshotTest
|
95
|
+
|
96
|
+
def create_attribute
|
97
|
+
Lecture0.attr_writer :lecturer
|
98
|
+
end
|
99
|
+
|
100
|
+
def setup
|
101
|
+
super
|
102
|
+
create_attribute # template method
|
103
|
+
snapshot!
|
104
|
+
assert_include? Lecture0.attributes, "lecturer"
|
105
|
+
Lecture0.attributes.delete("lecturer") # bad style this is
|
106
|
+
# now Lecture2 is like having removed all attributes
|
107
|
+
assert_not_include? Lecture0.attributes, "lecturer"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class AttrAccessorMovesTest < AttributeAccessorsMoveTest
|
112
|
+
|
113
|
+
def create_attribute
|
114
|
+
Lecture0.attr_accessor :lecturer
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_to_attr_reader
|
118
|
+
Lecture0.attr_reader :lecturer
|
119
|
+
assert_migration_string ""
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_to_attr_writer
|
123
|
+
Lecture0.attr_writer :lecturer
|
124
|
+
assert_migration_string ""
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_to_attr_accessor
|
128
|
+
Lecture0.attr_accessor :lecturer
|
129
|
+
assert_migration_string ""
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class AttrReaderMovesTest < AttributeAccessorsMoveTest
|
134
|
+
def create_attribute
|
135
|
+
Lecture0.attr_reader :lecturer
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_to_attr_reader
|
139
|
+
Lecture0.attr_reader :lecturer
|
140
|
+
assert_migration_string ""
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_to_attr_writer
|
144
|
+
Lecture0.attr_writer :lecturer
|
145
|
+
assert_migration_string "#new instance method: Lecture0.new.lecturer="
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_to_attr_accessor
|
149
|
+
Lecture0.attr_accessor :lecturer
|
150
|
+
assert_migration_string "#new instance method: Lecture0.new.lecturer="
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
class AttrWriterMovesTest < AttributeAccessorsMoveTest
|
155
|
+
def create_attribute
|
156
|
+
Lecture0.attr_writer :lecturer
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_to_attr_reader
|
160
|
+
Lecture0.attr_reader :lecturer
|
161
|
+
assert_migration_string "#new instance method: Lecture0.new.lecturer"
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_to_attr_writer
|
165
|
+
Lecture0.attr_writer :lecturer
|
166
|
+
assert_migration_string ""
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_to_attr_accessor
|
170
|
+
Lecture0.attr_accessor :lecturer
|
171
|
+
assert_migration_string "#new instance method: Lecture0.new.lecturer"
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "migration/test_project.rb"
|
2
|
+
|
3
|
+
class NeedMigrateUpBeforeAutomigration < ProjectTest
|
4
|
+
|
5
|
+
def setup
|
6
|
+
Maglev.abort_transaction
|
7
|
+
@project_name = 'project2'
|
8
|
+
super
|
9
|
+
Maglev::PERSISTENT_ROOT[:last_snapshot] = nil
|
10
|
+
Maglev.commit_transaction
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
super
|
15
|
+
Maglev.abort_transaction
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_no_snapshot_at_start
|
19
|
+
Maglev.abort_transaction
|
20
|
+
assert_nil Maglev::PERSISTENT_ROOT[:last_snapshot]
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_migrate_up_creates_a_snapshot
|
24
|
+
rake('migrate:up')
|
25
|
+
Maglev.abort_transaction
|
26
|
+
snap = Maglev::PERSISTENT_ROOT[:last_snapshot]
|
27
|
+
assert_not_nil snap
|
28
|
+
assert_include? snap.snapshot_classes, ProjectModel
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_migrate_auto_without_initial_snapshot_does_not_work
|
32
|
+
rake_output = rake('migrate:auto')
|
33
|
+
assert_equal "rake migrate:up has to be done first\n", rake_output
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_migrate_auto2_without_initial_snapshot_does_not_work
|
37
|
+
rake_output = rake('migrate:auto?')
|
38
|
+
assert_equal "rake migrate:up has to be done first\n", rake_output
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "automigration/rake_task_base"
|
2
|
+
|
3
|
+
class TestAutomigrationShow < RakeTaskTestBase
|
4
|
+
|
5
|
+
def test_automigrate_has_no_output_if_no_changes
|
6
|
+
rake_output = rake("migrate:auto?")
|
7
|
+
assert_equal "# no changes\n", rake_output
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_project_model_is_new
|
11
|
+
project_model_source("class ProjectModel
|
12
|
+
include MaglevRecord::Base
|
13
|
+
def x; end
|
14
|
+
end")
|
15
|
+
rake_output = rake("migrate:auto?")
|
16
|
+
assert_equal "#new class: ProjectModel\n", rake_output
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'more_asserts'
|
2
|
+
require 'temp_dir_test'
|
3
|
+
|
4
|
+
class SuperclassOfX
|
5
|
+
end
|
6
|
+
class NotSuperclassOfX
|
7
|
+
end
|
8
|
+
|
9
|
+
class SuperclassMismatchMigrationStringTest < TempDirTest
|
10
|
+
|
11
|
+
def remove_classes
|
12
|
+
Object.remove_const "XX" if defined? XX
|
13
|
+
Object.remove_const "XY" if defined? XY
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
remove_classes
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup
|
21
|
+
super
|
22
|
+
remove_classes
|
23
|
+
@fp = write_to_file("class XX < SuperclassOfX;include MaglevRecord::Base;def h;5;end;end;
|
24
|
+
class XY;include MaglevRecord::Base;attr_accessor :a;end")
|
25
|
+
snapshot = MaglevRecord::Snapshot.with_files([@fp])
|
26
|
+
write_to_file("class XX < NotSuperclassOfX;\ninclude MaglevRecord::Base;def h;end;end
|
27
|
+
class XY;include MaglevRecord::Base;attr_accessor :b;end", @fp)
|
28
|
+
@changes = snapshot.changes_in_files
|
29
|
+
end
|
30
|
+
|
31
|
+
def changes
|
32
|
+
@changes
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_no_class_changes_or_was_removed
|
36
|
+
assert_equal [], changes.new_class_names
|
37
|
+
assert_equal [], changes.removed_class_names
|
38
|
+
assert_equal [], changes.changed_class_names, "class XY changed but can not be listed here"
|
39
|
+
assert_equal [], changes.new_classes
|
40
|
+
assert_equal [], changes.removed_classes
|
41
|
+
assert_equal [], changes.changed_classes, "class XY changed but can not be listed here"
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_the_state_of_all_classes_is_restored
|
45
|
+
assert_equal ['a'], XY.attributes
|
46
|
+
assert_equal XX.instance_methods(false), ["h"]
|
47
|
+
assert_equal 5, XX.new.h
|
48
|
+
end
|
49
|
+
|
50
|
+
def superclass_mismatch_change
|
51
|
+
assert_equal 1, changes.superclass_mismatch_classes.size
|
52
|
+
changes.superclass_mismatch_classes.first
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_class_X_has_the_superclass_mismatch
|
56
|
+
assert_equal XX, superclass_mismatch_change.mismatching_class
|
57
|
+
assert_equal "XX", superclass_mismatch_change.class_name
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_superclass_mismatch_migration_string
|
61
|
+
assert_equal "# TypeError: superclass mismatch for XX\n" +
|
62
|
+
"# in #{@fp}\n" +
|
63
|
+
"XX.change_superclass_to NotSuperclassOfX",
|
64
|
+
changes.migration_string
|
65
|
+
assert_equal " # TypeError: superclass mismatch for XX\n" +
|
66
|
+
" # in #{@fp}\n" +
|
67
|
+
" XX.change_superclass_to NotSuperclassOfX",
|
68
|
+
changes.migration_string(4)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_changes_changed!
|
72
|
+
assert_not changes.nothing_changed?
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class NoSuperclassMismatchTest < Test::Unit::TestCase
|
77
|
+
def test_no_superclass_mismatch
|
78
|
+
s = MaglevRecord::Snapshot.new
|
79
|
+
changes = s.changes_since(s)
|
80
|
+
assert_equal [], changes.superclass_mismatch_classes
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
data/test/example_model.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
|
1
2
|
class Book
|
2
3
|
include MaglevRecord::ReadWrite
|
4
|
+
include MaglevRecord::Snapshotable
|
5
|
+
|
3
6
|
attr_accessor :author, :title, :comments
|
4
7
|
def self.example_params
|
5
8
|
{ :author => "Author", :title => "Title" }
|
@@ -11,6 +14,9 @@ end
|
|
11
14
|
|
12
15
|
class RootedBook < Book
|
13
16
|
include MaglevRecord::RootedBase
|
17
|
+
# TODO: why does rooted book change the ancestors of book?
|
18
|
+
validates :author, :presence => true,
|
19
|
+
:length => { :minimum => 4 }
|
14
20
|
def book
|
15
21
|
puts "I am a RootedBook"
|
16
22
|
end
|
@@ -25,8 +31,4 @@ RootedBook.maglev_record_persistable
|
|
25
31
|
UnrootedBook.maglev_record_persistable
|
26
32
|
Maglev.commit_transaction
|
27
33
|
|
28
|
-
|
29
|
-
include ActiveModel::Validations
|
30
|
-
validates :author, :presence => true,
|
31
|
-
:length => { :minimum => 4 }
|
32
|
-
end
|
34
|
+
RootedBook.redo_include_and_extend
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "maglev_record"
|
2
|
+
|
3
|
+
class BaseLecture1
|
4
|
+
maglev_record_persistable
|
5
|
+
include MaglevRecord::RootedBase
|
6
|
+
|
7
|
+
def initialize(lecturer, users)
|
8
|
+
@lecturer = lecturer
|
9
|
+
@users = users
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.fill_with_examples
|
13
|
+
self.clear
|
14
|
+
self.new("Hans Ullrich", ["Peter Garstig", "Elfride Bricht", "Sergey Faehrlich"])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class BaseLecture2
|
19
|
+
maglev_record_persistable
|
20
|
+
include MaglevRecord::RootedBase
|
21
|
+
|
22
|
+
attr_accessor :lecturer, :users
|
23
|
+
|
24
|
+
def self.fill_with_examples
|
25
|
+
self.clear
|
26
|
+
lecture = self.new()
|
27
|
+
lecture.lecturer = "Hans Ullrich"
|
28
|
+
lecture.users = ["Peter Garstig", "Elfride Bricht", "Sergey Faehrlich"]
|
29
|
+
end
|
30
|
+
end
|
@@ -1,36 +1,74 @@
|
|
1
1
|
require 'more_asserts'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'migration/base_lectures'
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
+
LECTURE_TEMPFILE = Tempfile.new(['lectures', '.rb'])
|
6
|
+
LECTURES_STRING = <<LectureString
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
#puts "Loading Lectures except these \#{LECTURES_NOT_TO_LOAD}"
|
9
|
+
|
10
|
+
unless LECTURES_NOT_TO_LOAD.include? 'Lecture0'
|
11
|
+
class Lecture0
|
12
|
+
# empty Lecture
|
13
|
+
include MaglevRecord::RootedBase
|
14
|
+
def x;end
|
9
15
|
end
|
16
|
+
end
|
10
17
|
|
11
|
-
|
12
|
-
|
13
|
-
|
18
|
+
unless LECTURES_NOT_TO_LOAD.include? 'Lecture'
|
19
|
+
class Lecture < BaseLecture1
|
20
|
+
def x;end
|
21
|
+
def self.x;end
|
22
|
+
def lecture2;false;end
|
14
23
|
end
|
15
24
|
end
|
16
25
|
|
17
|
-
|
18
|
-
|
26
|
+
unless LECTURES_NOT_TO_LOAD.include? 'Lecture2'
|
27
|
+
class Lecture2 < BaseLecture2
|
28
|
+
def x;end
|
29
|
+
def lecture2;true;end
|
30
|
+
end
|
31
|
+
end
|
19
32
|
|
20
|
-
|
33
|
+
unless LECTURES_NOT_TO_LOAD.include? 'Lecture3'
|
34
|
+
class Lecture3 < Lecture
|
35
|
+
def x;end
|
36
|
+
def self.x;end
|
37
|
+
def lecture3;true;end
|
38
|
+
end
|
39
|
+
end
|
21
40
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
lecture.lecturer = "Hans Ullrich"
|
26
|
-
lecture.users = ["Peter Garstig", "Elfride Bricht", "Sergey Faehrlich"]
|
41
|
+
unless LECTURES_NOT_TO_LOAD.include? 'Lecture4'
|
42
|
+
class Lecture4 < Lecture
|
43
|
+
def x;end
|
27
44
|
end
|
28
45
|
end
|
29
46
|
|
47
|
+
module Models
|
48
|
+
module M1
|
49
|
+
class Lecture < BaseLecture2
|
50
|
+
def x;end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
module M2
|
54
|
+
end
|
55
|
+
module M3
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
"Lecture Lecture0 Lecture2 Lecture3 Lecture4".split.each do |const|
|
60
|
+
Object.const_get(const).maglev_record_persistable if Object.const_defined? const
|
61
|
+
end
|
62
|
+
|
63
|
+
LectureString
|
64
|
+
|
65
|
+
LECTURES_NOT_TO_LOAD = [] # a list of lectures that are removed from the file
|
66
|
+
|
30
67
|
class Test::Unit::TestCase
|
31
68
|
|
32
69
|
def self.teardown_migration_operations
|
33
|
-
|
70
|
+
Maglev.abort_transaction
|
71
|
+
[:Lecture, :Lecture2, :Lecture3, :Lecture4, :Lecture0].each{ |const|
|
34
72
|
if Object.const_defined? const
|
35
73
|
Object.const_get(const).clear
|
36
74
|
Maglev.persistent do
|
@@ -38,6 +76,9 @@ class Test::Unit::TestCase
|
|
38
76
|
end
|
39
77
|
end
|
40
78
|
}
|
79
|
+
Maglev.commit_transaction
|
80
|
+
LECTURE_TEMPFILE.rewind
|
81
|
+
LECTURE_TEMPFILE.write " " * LECTURE_TEMPFILE.size
|
41
82
|
end
|
42
83
|
|
43
84
|
def self.setup_migration_operations
|
@@ -46,46 +87,15 @@ class Test::Unit::TestCase
|
|
46
87
|
end
|
47
88
|
|
48
89
|
def self.redefine_migration_classes
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
class Lecture3 < Lecture
|
57
|
-
end
|
58
|
-
|
59
|
-
class Lecture4 < Lecture
|
60
|
-
end
|
61
|
-
|
62
|
-
module Models
|
63
|
-
module M1
|
64
|
-
class Lecture < BaseLecture2
|
65
|
-
end
|
66
|
-
end
|
67
|
-
module M2
|
68
|
-
end
|
69
|
-
module M3
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
[Lecture, Lecture2, Lecture3, Lecture4].each do |const|
|
74
|
-
const.maglev_record_persistable
|
75
|
-
end
|
76
|
-
"
|
77
|
-
end
|
78
|
-
|
79
|
-
def setup_migration_operations
|
80
|
-
self.class.setup_migration_operations
|
81
|
-
end
|
82
|
-
|
83
|
-
def teardown_migration_operations
|
84
|
-
self.class.teardown_migration_operations
|
90
|
+
LECTURE_TEMPFILE.rewind
|
91
|
+
LECTURE_TEMPFILE.write LECTURES_STRING
|
92
|
+
LECTURES_NOT_TO_LOAD.delete_if{|i| true}
|
93
|
+
Maglev.abort_transaction
|
94
|
+
Kernel.load LECTURE_TEMPFILE.path
|
95
|
+
Maglev.commit_transaction
|
85
96
|
end
|
86
97
|
|
87
|
-
|
88
|
-
|
89
|
-
end
|
98
|
+
as_instance_method :setup_migration_operations, :teardown_migration_operations
|
99
|
+
as_instance_method :redefine_migration_classes
|
90
100
|
|
91
101
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile ~/.gitignore_global
|
6
|
+
|
7
|
+
# Ignore bundler config
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore the default SQLite database.
|
11
|
+
/db/*.sqlite3
|
12
|
+
|
13
|
+
# Ignore all logfiles and tempfiles.
|
14
|
+
/log/*.log
|
15
|
+
/tmp
|