maglevrecord 0.0.3 → 0.1.1

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.
Files changed (161) hide show
  1. data/.gitignore +35 -0
  2. data/.travis.yml +19 -0
  3. data/Gemfile +13 -0
  4. data/README.md +89 -0
  5. data/Rakefile +22 -0
  6. data/install.sh +238 -0
  7. data/lib/maglev_record/base.rb +10 -62
  8. data/lib/maglev_record/enumerable.rb +13 -24
  9. data/lib/maglev_record/errors.rb +10 -0
  10. data/lib/maglev_record/integration.rb +7 -0
  11. data/lib/maglev_record/maglev_record.rb +13 -0
  12. data/lib/maglev_record/maglev_support/active_support_patch.rb +31 -0
  13. data/lib/maglev_record/maglev_support/concern.rb +19 -0
  14. data/lib/maglev_record/maglev_support/maglev_support.rb +15 -0
  15. data/lib/maglev_record/maglev_support/secure_password.rb +39 -0
  16. data/lib/maglev_record/migration/loader.rb +38 -0
  17. data/lib/maglev_record/migration/migration.rb +142 -0
  18. data/lib/maglev_record/migration/migrator.rb +40 -0
  19. data/lib/maglev_record/migration/operations.rb +92 -0
  20. data/lib/maglev_record/migration.rb +5 -0
  21. data/lib/maglev_record/persistence.rb +23 -48
  22. data/lib/maglev_record/raketasks.rb +9 -0
  23. data/lib/maglev_record/read_write.rb +20 -10
  24. data/lib/maglev_record/rooted_base.rb +8 -0
  25. data/lib/maglev_record/rooted_enumerable.rb +25 -0
  26. data/lib/maglev_record/rooted_persistence.rb +36 -0
  27. data/lib/maglev_record/sensible.rb +28 -0
  28. data/lib/maglev_record/snapshot/change.rb +53 -0
  29. data/lib/maglev_record/snapshot/snapshot.rb +67 -0
  30. data/lib/maglev_record/snapshot/snapshotable.rb +58 -0
  31. data/lib/maglev_record/snapshot.rb +5 -0
  32. data/lib/maglev_record/tools/object_reference.rb +189 -0
  33. data/lib/maglev_record/tools/submodule_finder.rb +42 -0
  34. data/lib/maglev_record/tools.rb +2 -0
  35. data/lib/maglev_record.rb +60 -4
  36. data/lib/tasks/database.rake +38 -0
  37. data/maglevrecord.gemspec +17 -0
  38. data/rails/init.rb +1 -0
  39. data/test/_test_object_reference.rb +70 -0
  40. data/test/example_model.rb +26 -13
  41. data/test/migration/dummy_migrations/migration_1.rb +8 -0
  42. data/test/migration/dummy_migrations/migration_2.rb +8 -0
  43. data/test/migration/dummy_migrations/migration_3.rb +8 -0
  44. data/test/migration/migrations/migration_1.rb +12 -0
  45. data/test/migration/migrations/migration_2.rb +12 -0
  46. data/test/migration/migrations/migration_3.rb +12 -0
  47. data/test/migration/operation_setup.rb +91 -0
  48. data/test/migration/projects/project1/.gitignore +15 -0
  49. data/test/migration/projects/project1/Gemfile +43 -0
  50. data/test/migration/projects/project1/Gemfile.lock +114 -0
  51. data/test/migration/projects/project1/README.rdoc +261 -0
  52. data/test/migration/projects/project1/Rakefile +17 -0
  53. data/test/migration/projects/project1/app/assets/images/rails.png +0 -0
  54. data/test/migration/projects/project1/app/assets/javascripts/application.js +15 -0
  55. data/test/migration/projects/project1/app/assets/stylesheets/application.css +13 -0
  56. data/test/migration/projects/project1/app/controllers/application_controller.rb +3 -0
  57. data/test/migration/projects/project1/app/helpers/application_helper.rb +2 -0
  58. data/test/migration/projects/project1/app/mailers/.gitkeep +0 -0
  59. data/test/migration/projects/project1/app/models/.gitkeep +0 -0
  60. data/test/migration/projects/project1/app/views/layouts/application.html.erb +14 -0
  61. data/test/migration/projects/project1/config/application.rb +62 -0
  62. data/test/migration/projects/project1/config/boot.rb +6 -0
  63. data/test/migration/projects/project1/config/database.yml +25 -0
  64. data/test/migration/projects/project1/config/environment.rb +5 -0
  65. data/test/migration/projects/project1/config/environments/development.rb +37 -0
  66. data/test/migration/projects/project1/config/environments/production.rb +67 -0
  67. data/test/migration/projects/project1/config/initializers/backtrace_silencers.rb +7 -0
  68. data/test/migration/projects/project1/config/initializers/inflections.rb +15 -0
  69. data/test/migration/projects/project1/config/initializers/mime_types.rb +5 -0
  70. data/test/migration/projects/project1/config/initializers/secret_token.rb +7 -0
  71. data/test/migration/projects/project1/config/initializers/session_store.rb +8 -0
  72. data/test/migration/projects/project1/config/initializers/wrap_parameters.rb +14 -0
  73. data/test/migration/projects/project1/config/locales/en.yml +5 -0
  74. data/test/migration/projects/project1/config/routes.rb +58 -0
  75. data/test/migration/projects/project1/config.ru +4 -0
  76. data/test/migration/projects/project1/db/seeds.rb +7 -0
  77. data/test/migration/projects/project1/lib/assets/.gitkeep +0 -0
  78. data/test/migration/projects/project1/lib/tasks/.gitkeep +0 -0
  79. data/test/migration/projects/project1/log/.gitkeep +0 -0
  80. data/test/migration/projects/project1/public/404.html +26 -0
  81. data/test/migration/projects/project1/public/422.html +26 -0
  82. data/test/migration/projects/project1/public/500.html +25 -0
  83. data/test/migration/projects/project1/public/favicon.ico +0 -0
  84. data/test/migration/projects/project1/public/index.html +241 -0
  85. data/test/migration/projects/project1/public/robots.txt +5 -0
  86. data/test/migration/projects/project1/script/rails +6 -0
  87. data/test/migration/projects/project2/.gitignore +15 -0
  88. data/test/migration/projects/project2/Gemfile +44 -0
  89. data/test/migration/projects/project2/Gemfile.lock +115 -0
  90. data/test/migration/projects/project2/README.rdoc +261 -0
  91. data/test/migration/projects/project2/Rakefile +17 -0
  92. data/test/migration/projects/project2/app/assets/images/rails.png +0 -0
  93. data/test/migration/projects/project2/app/assets/javascripts/application.js +15 -0
  94. data/test/migration/projects/project2/app/assets/stylesheets/application.css +13 -0
  95. data/test/migration/projects/project2/app/controllers/application_controller.rb +3 -0
  96. data/test/migration/projects/project2/app/helpers/application_helper.rb +2 -0
  97. data/test/migration/projects/project2/app/mailers/.gitkeep +0 -0
  98. data/test/migration/projects/project2/app/models/.gitkeep +0 -0
  99. data/test/migration/projects/project2/app/models/project_model.rb +8 -0
  100. data/test/migration/projects/project2/app/views/layouts/application.html.erb +14 -0
  101. data/test/migration/projects/project2/config/application.rb +62 -0
  102. data/test/migration/projects/project2/config/boot.rb +6 -0
  103. data/test/migration/projects/project2/config/database.yml +25 -0
  104. data/test/migration/projects/project2/config/environment.rb +5 -0
  105. data/test/migration/projects/project2/config/environments/development.rb +37 -0
  106. data/test/migration/projects/project2/config/environments/production.rb +67 -0
  107. data/test/migration/projects/project2/config/initializers/backtrace_silencers.rb +7 -0
  108. data/test/migration/projects/project2/config/initializers/inflections.rb +15 -0
  109. data/test/migration/projects/project2/config/initializers/mime_types.rb +5 -0
  110. data/test/migration/projects/project2/config/initializers/secret_token.rb +7 -0
  111. data/test/migration/projects/project2/config/initializers/session_store.rb +8 -0
  112. data/test/migration/projects/project2/config/initializers/wrap_parameters.rb +14 -0
  113. data/test/migration/projects/project2/config/locales/en.yml +5 -0
  114. data/test/migration/projects/project2/config/routes.rb +58 -0
  115. data/test/migration/projects/project2/config.ru +4 -0
  116. data/test/migration/projects/project2/db/seeds.rb +7 -0
  117. data/test/migration/projects/project2/lib/assets/.gitkeep +0 -0
  118. data/test/migration/projects/project2/lib/tasks/.gitkeep +0 -0
  119. data/test/migration/projects/project2/log/.gitkeep +0 -0
  120. data/test/migration/projects/project2/migrations/migration_2013-04-Apr-23_17.31.38.rb +16 -0
  121. data/test/migration/projects/project2/migrations/migration_2013-04-Apr-23_17.31.52.rb +16 -0
  122. data/test/migration/projects/project2/migrations/migration_2013-04-Apr-23_17.32.07.rb +16 -0
  123. data/test/migration/projects/project2/public/404.html +26 -0
  124. data/test/migration/projects/project2/public/422.html +26 -0
  125. data/test/migration/projects/project2/public/500.html +25 -0
  126. data/test/migration/projects/project2/public/favicon.ico +0 -0
  127. data/test/migration/projects/project2/public/index.html +241 -0
  128. data/test/migration/projects/project2/public/robots.txt +5 -0
  129. data/test/migration/projects/project2/script/rails +6 -0
  130. data/test/migration/test_loader.rb +78 -0
  131. data/test/migration/test_migration.rb +127 -0
  132. data/test/migration/test_nonexistent_classes.rb +120 -0
  133. data/test/migration/test_operations_fit_together.rb +68 -0
  134. data/test/migration/test_project.rb +105 -0
  135. data/test/migration/test_project1.slow.rb +58 -0
  136. data/test/migration/test_project2.slow.rb +34 -0
  137. data/test/migration/test_remove.rb +219 -0
  138. data/test/migration/test_rename.rb +238 -0
  139. data/test/migration/test_scenario.rb +37 -0
  140. data/test/migration/todo.txt +17 -0
  141. data/test/more_asserts.rb +63 -0
  142. data/test/snapshot/test_snapshot.rb +99 -0
  143. data/test/snapshot/test_snapshot_attributes.slow.rb +57 -0
  144. data/test/snapshot/test_snapshot_classes.slow.rb +32 -0
  145. data/test/snapshot/test_snapshotable.rb +53 -0
  146. data/test/test_accessors.rb +46 -0
  147. data/test/test_active_model_like_interface.rb +1 -1
  148. data/test/test_model_timestamps.rb +22 -0
  149. data/test/test_more_asserts.rb +68 -0
  150. data/test/test_naming.rb +22 -0
  151. data/test/test_persistence.rb +127 -0
  152. data/test/test_query_interface.rb +20 -25
  153. data/test/test_sensibles.rb +38 -0
  154. data/test/test_validation.rb +20 -57
  155. data/todo.txt +1 -0
  156. data/update.sh +180 -0
  157. metadata +156 -12
  158. data/lib/maglev_record/model_not_saved_or_reset.rb +0 -15
  159. data/test/test_dirty_object.rb +0 -50
  160. data/test/test_maglev_record_base.rb +0 -22
  161. data/test/test_maglev_simple_persistance.rb +0 -45
@@ -0,0 +1,67 @@
1
+ require "maglev_record/snapshot/change"
2
+
3
+ module MaglevRecord
4
+ class ClassSnapshot
5
+ def initialize(cls)
6
+ @snapshot_class = cls
7
+ @attr_readers = cls.attr_readers
8
+ @files = cls.file_paths
9
+ @exists = cls.has_definitions?
10
+ end
11
+
12
+ def exists?
13
+ @exists
14
+ end
15
+
16
+ def ==(other)
17
+ self.snapshot_class == other.snapshot_class \
18
+ and self.exists? == other.exists?
19
+ end
20
+
21
+ alias :eql? :==
22
+
23
+ def snapshot_class
24
+ @snapshot_class
25
+ end
26
+
27
+ def changes_since(older)
28
+ return nil unless changed_since?(older)
29
+ ClassChange.new(older, self)
30
+ end
31
+
32
+ def changed_since?(older)
33
+ attr_readers != older.attr_readers
34
+ end
35
+
36
+ def attr_readers
37
+ @attr_readers
38
+ end
39
+
40
+ def class_name
41
+ @snapshot_class.name
42
+ end
43
+ end
44
+
45
+ class Snapshot
46
+
47
+ def for_class(cls)
48
+ ClassSnapshot.new(cls)
49
+ end
50
+
51
+ def initialize
52
+ @class_snapshots = Snapshotable.snapshotable_classes.map{ |cls|
53
+ for_class cls
54
+ }
55
+ end
56
+
57
+ def changes_since(older)
58
+ Change.new(older, self)
59
+ end
60
+
61
+ def class_snapshots
62
+ Array.new(@class_snapshots)
63
+ end
64
+
65
+ end
66
+ end
67
+
@@ -0,0 +1,58 @@
1
+ Maglev.persistent do
2
+ class ::Class
3
+ def exist!
4
+ @exists = true
5
+ end
6
+
7
+ def start_existence_test!
8
+ @exists = false
9
+ end
10
+
11
+ def exists?
12
+ return true if @exists
13
+ false
14
+ end
15
+ end
16
+ end
17
+
18
+ module MaglevRecord
19
+ module Snapshotable
20
+ def self.snapshotable_classes
21
+ classes = []
22
+ Object.constants.each { |constant|
23
+ begin
24
+ cls = Object.const_get constant
25
+ rescue Exception
26
+ else
27
+ classes << cls if cls.is_a? Class and cls.ancestors.include? self
28
+ end
29
+ }
30
+ classes
31
+ end
32
+
33
+ module ClassMethods
34
+
35
+ def self.extended(base)
36
+ base.exist! if base.respond_to? :exist!
37
+ end
38
+
39
+ def file_paths
40
+ (self.instance_methods(false).map { |m|
41
+ self.instance_method(m).source_location.first
42
+ } + self.methods(false).map { |m|
43
+ self.method(m).source_location.first
44
+ }).uniq
45
+ end
46
+
47
+ def has_definitions?
48
+ # TODO: maybe in a nested transaction?
49
+ start_existence_test!
50
+ file_paths.each{ |file_path|
51
+ Kernel.load file_path if File.file? file_path
52
+ return true if exists?
53
+ }
54
+ exists?
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ require "maglev_record/snapshot/snapshotable"
2
+ require "maglev_record/snapshot/change"
3
+ require "maglev_record/snapshot/snapshot"
4
+
5
+
@@ -0,0 +1,189 @@
1
+
2
+
3
+ class Object
4
+ #
5
+ # breadth first search for references from the given object to self
6
+ #
7
+ def reference_path_to(to_object, length, trace = false)
8
+ paths = [[to_object]]
9
+ traversed = IdentitySet.new
10
+ traversed.add(to_object)
11
+ start_size = 1 if trace
12
+ while not paths.empty? and paths.first.size <= length
13
+ references = paths[0][0].find_references_in_memory
14
+ # if we print here a SecurityError mey occur
15
+ references.each{ |reference|
16
+ return [reference] + paths[0] if reference.equal?(self)
17
+ unless traversed.include?(reference) or paths.any?{ |path| reference.equal?(path)}
18
+ paths.push([reference] + paths[0])
19
+ traversed.add(reference)
20
+ end
21
+ }
22
+ if trace and start_size != paths[0].size
23
+ puts "reference_path_length: #{paths[0].size}"
24
+ start_size = paths[0].size
25
+ end
26
+ paths.delete_at(0)
27
+ end
28
+ return nil
29
+ end
30
+
31
+ def __hash_key_value
32
+ begin
33
+ assoc_value = instance_variable_defined?(:@_st_value)
34
+ assoc_key = instance_variable_defined?(:@_st_key)
35
+ rescue NameError
36
+ return nil
37
+ end
38
+ return nil unless assoc_key and assoc_value
39
+ return [assoc_key, assoc_value]
40
+ end
41
+
42
+ def __hash_key_value_equal_to(anObject)
43
+ value = __hash_key_value
44
+ return nil if value.nil?
45
+ assoc_key, assoc_value = value
46
+ return nil unless assoc_key.equal?(anObject) or assoc_value.equal?(anObject)
47
+ return [assoc_key, assoc_value]
48
+ end
49
+
50
+ def __instance_variable_equal_to(anObject)
51
+ return nil unless self.respond_to?(:instance_variables) and self.respond_to?(:instance_variable_get)
52
+ self.instance_variables.each{ |v|
53
+ return v if self.instance_variable_get(v).equal?(anObject)
54
+ }
55
+ return nil
56
+ end
57
+
58
+ def __eigenclass_equal_to(anObject)
59
+ # breaks maglev if this is used by
60
+ # maglev-ruby -e "require 'object_reference'; o = Object.new; start = Time.now; f = o.string_reference_path_to(true, 20); p start - Time.now; puts f"
61
+ return false if self.class.equal?(Array)
62
+ eigenclass = class << self
63
+ self
64
+ end
65
+ eigenclass.equal? anObject
66
+ end
67
+
68
+ def __incuded_module_equal_to(anObject)
69
+ included_modules.any?{ |m| m.equal?(anObject)} if respond_to? :included_modules
70
+ end
71
+
72
+ # format the reference path
73
+ # returns a human readable string
74
+ #
75
+ # length
76
+ # the maximum length of the path
77
+ #
78
+ # width_of_line
79
+ # the maximum size of a line
80
+ #
81
+ # trace
82
+ # true if reference_path_length shall be printed to stdout to trace the progress
83
+ # false otherwise
84
+ #
85
+ # pretty
86
+ # true if module includes shall be detected
87
+ # false if maglev internals shall be revealed
88
+ #
89
+ def string_reference_path_to(to_object, length = 10, width_of_line = 80, trace = true, pretty = true)
90
+ reference_path = reference_path_to(to_object, length, trace)
91
+ return "" if reference_path.nil?
92
+ lines = []
93
+ left_column_size = 0
94
+ referenced_index = 0
95
+ while referenced_index < reference_path.size - 1
96
+ # prepare loop
97
+ object = reference_path[referenced_index]
98
+ referenced = reference_path[referenced_index + 1]
99
+ referenced_index += 1
100
+ name_of_referenced = '?? of'
101
+ inspect_string = nil
102
+ # switch case on displaying references
103
+ begin
104
+ # puts "#obj: #{object.inspect} #{referenced.inspect} at: #{referenced_index}\n\n"
105
+ # object --> class
106
+ if object.class.equal?(referenced)
107
+ name_of_referenced = 'class of'
108
+ # class --> superclass
109
+ elsif object.respond_to? :superclass and object.superclass.equal?(referenced)
110
+ name_of_referenced = 'superclass of'
111
+ # included
112
+ elsif pretty and object.__incuded_module_equal_to(reference_path[referenced_index + 2])
113
+ name_of_referenced = 'included by'
114
+ referenced = reference_path[referenced_index + 2]
115
+ referenced_index += 2
116
+ # OrderPreservingHashAssociation --> ...
117
+ elsif not object.__hash_key_value_equal_to(referenced).nil?
118
+ assoc_key, assoc_value = object.__hash_key_value_equal_to(referenced)
119
+ if assoc_value.equal?(referenced)
120
+ name_of_referenced = 'value of'
121
+ elsif assoc_key.equal?(referenced)
122
+ name_of_referenced = 'key of'
123
+ end
124
+ # ... --> OrderPreservingHashAssociation
125
+ elsif not referenced.__hash_key_value.nil?
126
+ assoc_key, assoc_value = referenced.__hash_key_value
127
+ inspect_string = "#{assoc_key.inspect} => #{assoc_value.inspect}"
128
+ name_of_referenced = 'association in'
129
+ # ... --> attribute
130
+ elsif not (variable = object.__instance_variable_equal_to(referenced)).nil?
131
+ name_of_referenced = variable.to_s + ' in'
132
+ # [...] -> object at index
133
+ elsif object.respond_to?(:find_index) and (index = object.find_index{ |element| element.equal?(referenced)})
134
+ name_of_referenced = "at #{index.inspect} of"
135
+ # eigenclass
136
+ elsif object.__eigenclass_equal_to(referenced)
137
+ name_of_referenced = "eigenclass of"
138
+ elsif referenced.__eigenclass_equal_to(object)
139
+ name_of_referenced = "eigenbase of"
140
+ end
141
+ rescue Exception => e
142
+ name_of_referenced = 'error'
143
+ referenced = e
144
+ end
145
+ begin
146
+ inspect_string = referenced.inspect if inspect_string.nil?
147
+ rescue
148
+ inspect_string = 'can not inspect this object'
149
+ end
150
+ lines << [name_of_referenced, inspect_string]
151
+ left_column_size = name_of_referenced.size if name_of_referenced.size > left_column_size
152
+ end
153
+ width_of_line -= 8 # subtract additional characters like ' is ' ' of '
154
+ right_column_size = width_of_line - left_column_size
155
+ right_column_size = 10 if right_column_size < 0
156
+ s = ""
157
+ lines.reverse.each{ |line|
158
+ s += "#{line[1][0..right_column_size]} is \n#{line[0].rjust(left_column_size)} "
159
+ }
160
+ return s + "#{reference_path[0].inspect}"
161
+ end
162
+ end
163
+
164
+ # TestCases
165
+
166
+ ## Hash
167
+ # maglev-ruby -e "require 'object_reference'; d = {a:'2', b: 34}; f = d.string_reference_path_to(d[:a], 3); puts f"
168
+
169
+ ## superclass
170
+ # maglev-ruby -e "require 'object_reference'; class AA;end; class BB < AA;end; class CC < BB; end; class DD < CC; end; class EE < DD; end; puts EE.string_reference_path_to(AA, 5)"
171
+
172
+ ## instance var
173
+ # maglev-ruby -e "require 'object_reference'; class AA; attr_accessor :x end; o = Object.new; aa = AA.new; aa.x = o; puts aa.string_reference_path_to(o, 3)"
174
+
175
+ ## class and instvar
176
+ # maglev-ruby -e "require 'object_reference'; class AA; attr_accessor :x end; class OO; end;o = OO.new; aa = AA.new; aa.x = o; bb = AA.new; bb.x = aa; cc = AA.new; cc.x = bb; puts cc.string_reference_path_to(OO, 5)"
177
+
178
+ ## Object.new references true
179
+ # maglev-ruby -e "require 'object_reference'; o = Object.new; start = Time.now; f = o.string_reference_path_to(true, 20); p start - Time.now; puts f"
180
+
181
+ ## Array
182
+ # maglev-ruby -e "require 'object_reference'; a = b = []; 20.times{a = [a]}; start = Time.now; f = a.string_reference_path_to(b, 20); p start - Time.now; puts f"
183
+
184
+ ## Eigenclass (x is eigenclass of y)
185
+ # maglev-ruby -e "require 'object_reference'; class X;end; x = class <<X;self;end; puts X.string_reference_path_to(x, 5)"
186
+
187
+ ## Eigenbase ( reverse of eigenclass)
188
+ # maglev-ruby -e "require 'object_reference'; class X;end; x = class <<X;self;end; puts x.string_reference_path_to(X, 5)"
189
+
@@ -0,0 +1,42 @@
1
+ class MaglevSupport::SubmoduleFinder
2
+ def submodules_for(*constants)
3
+ whole_set = Set.new
4
+ constants.each do |constant|
5
+ @referenced_modules = Set.new
6
+ reference(constant)
7
+ whole_set = whole_set.union(@referenced_modules.select do |mod|
8
+ mod.name.to_s.include?(constant.to_s)
9
+ end)
10
+ end
11
+ constants + whole_set.to_a.sort_by do |mod| mod.name end
12
+ end
13
+
14
+ def reference(constant)
15
+ return if @referenced_modules.include?(constant)
16
+ @referenced_modules.add(constant)
17
+
18
+ submodules = constant.constants.map do |const|
19
+ begin
20
+ constant.const_get(const)
21
+ rescue Exception => e; end
22
+ end.select do |mod|
23
+ # We only want constants which are classes or modules, e.g. no Fixnums, Strings, ...
24
+ [Module, Class].include?(mod.class)
25
+ end
26
+
27
+ submodules.each do |mod|
28
+ reference(mod)
29
+ end
30
+ end
31
+ private :reference
32
+ end
33
+
34
+ if __FILE__ == $0
35
+ # EXAMPLE USAGE
36
+ require "rubygems"
37
+ require "rake"
38
+ puts "Finding all submodules of Rake."
39
+ ref_finder = SubmoduleFinder.new
40
+ referenced_modules = ref_finder.submodules_for(Rake)
41
+ puts referenced_modules.to_a.map { |mod| mod.name }.sort.inspect
42
+ end
@@ -0,0 +1,2 @@
1
+ require "maglev_record/tools/object_reference"
2
+ require "maglev_record/tools/submodule_finder"
data/lib/maglev_record.rb CHANGED
@@ -1,4 +1,60 @@
1
- require "rubygems"
2
- require "maglev_record/model_not_saved_or_reset"
3
- require "maglev_record/base"
4
- require "maglev_record/persistence"
1
+ require "active_model"
2
+ require "active_support"
3
+ require "active_support/core_ext/class/attribute"
4
+ require "maglev_record/maglev_support/maglev_support"
5
+ require "maglev_record/tools"
6
+ require "bundler/setup"
7
+ require "maglev_record/maglev_support/concern"
8
+ require "set"
9
+ require "logger"
10
+
11
+ if defined? MaglevRecord::VERSION
12
+ if defined? RootedBook
13
+ RootedBook.redo_include_and_extend
14
+ end
15
+ if defined? UnrootedBook
16
+ UnrootedBook.redo_include_and_extend
17
+ end
18
+ MaglevRecord::Migration.redo_include_and_extend
19
+ else
20
+ puts "IT IS NOT DEFINED"
21
+ # require "maglev_record/tools"
22
+ require "maglev_record/maglev_record"
23
+
24
+ require "maglev_record/snapshot"
25
+ require "maglev_record/maglev_support/secure_password"
26
+ require "maglev_record/sensible"
27
+ require "maglev_record/rooted_enumerable"
28
+ require "maglev_record/enumerable"
29
+ require "maglev_record/errors"
30
+ require "maglev_record/integration"
31
+ require "maglev_record/persistence"
32
+ require "maglev_record/read_write"
33
+ require "maglev_record/rooted_persistence"
34
+ require "maglev_record/migration"
35
+ require "maglev_record/base"
36
+ require "maglev_record/rooted_base"
37
+
38
+ module MaglevRecord
39
+ ref_finder = MaglevSupport::SubmoduleFinder.new
40
+ referenced_modules = ref_finder.submodules_for(MaglevRecord, MaglevSupport, Set)
41
+ MAGLEV_RECORD_PROC = Proc.new do |superklass_module|
42
+ referenced_modules.include?(superklass_module)
43
+ end
44
+
45
+ Maglev.persistent do
46
+ class ::Module
47
+ def maglev_record_persistable
48
+ self.maglev_persistable(true, &MAGLEV_RECORD_PROC)
49
+ end
50
+ end
51
+ end
52
+
53
+ referenced_modules.each do |mod|
54
+ mod.maglev_record_persistable
55
+ end
56
+ end
57
+ end
58
+
59
+ ActiveModel::Errors.maglev_nil_references
60
+ Maglev.commit_transaction
@@ -0,0 +1,38 @@
1
+ require "maglev_record/migration"
2
+ require "time"
3
+ require "logger"
4
+ require "fileutils"
5
+
6
+ MIGRATION_FOLDER = "migrations"
7
+
8
+ desc "transform the maglev database"
9
+ namespace :migrate do
10
+
11
+ desc "set up the project for migrations"
12
+ task :setup do
13
+ # puts "PID: #{Process.pid} stone: #{Maglev::System.stone_name}"
14
+ FileUtils.mkpath(MIGRATION_FOLDER) unless File.directory?(MIGRATION_FOLDER)
15
+ end
16
+
17
+ desc "migrate all the migrations in the migration folder"
18
+ task :up => :setup do
19
+ loader = MaglevRecord::MigrationLoader.new
20
+ loader.load_directory(MIGRATION_FOLDER)
21
+ migrator = MaglevRecord::Migrator.new(loader.migration_list)
22
+ logger = Logger.new(STDOUT)
23
+ migrator.up(logger)
24
+ end
25
+
26
+ desc "create a new migration in the migration folder"
27
+ task :new => :setup do
28
+ now = Time.now
29
+ filename = now.strftime("migration_%Y-%m-%b-%d_%H.%M.%S.rb")
30
+ content = MaglevRecord::Migration.file_content(now, 'fill in description here')
31
+ filepath = File.join(MIGRATION_FOLDER, filename)
32
+ File.open(filepath, 'w') { |file|
33
+ file.write(content)
34
+ }
35
+ puts "created migration #{filepath}"
36
+ end
37
+ end
38
+
@@ -0,0 +1,17 @@
1
+ require File.expand_path "lib/maglev_record/maglev_record"
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'maglevrecord'
5
+ s.version = MaglevRecord::VERSION
6
+ s.date = '2013-05-06'
7
+ s.summary = "MagLev persistence with an ActiveRecord-like interface!"
8
+ s.description = "Library for using to MagLev to persist your data in a Rails app."
9
+ s.authors = ["Dimitri Korsch", "Kirstin Heidler", "Nicco Kunzmann", "Matthias Springer", "Stefan Bunk"]
10
+ s.files = `git ls-files`.split("\n")
11
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
12
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
13
+ s.email = "bp2012h1@hpi.uni-potsdam.de"
14
+ s.homepage = 'https://github.com/knub/maglevrecord'
15
+ s.require_path = 'lib'
16
+
17
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ Kernel.load File.join(File.dirname(__FILE__), '..', 'init.rb')
@@ -0,0 +1,70 @@
1
+ require "maglev_record"
2
+
3
+ # use
4
+ # bundle exec rake test TESTOPTS="-v" TEST=test/_test_object_reference.rb
5
+
6
+
7
+ module Mod
8
+
9
+ end
10
+
11
+ class AA
12
+ include Mod
13
+ attr_accessor :x
14
+ end
15
+ class BB < AA
16
+ end
17
+ class CC < BB
18
+ end
19
+ class DD < CC
20
+ end
21
+ class EE < DD
22
+ end
23
+ class OO
24
+ end
25
+ class X
26
+ end
27
+
28
+ o = OO.new
29
+ d = {a:'2', b: 34}
30
+ aa = AA.new
31
+ aa.x = o;
32
+ bb = AA.new
33
+ bb.x = aa
34
+ cc = AA.new
35
+ cc.x = bb
36
+ a = b = []
37
+ 20.times{ a = [a] }
38
+ x = class << X
39
+ self
40
+ end
41
+
42
+ def self.assert_equal(v1, v2)
43
+ raise "expected \n#{v1.inspect}\n == \n#{v2.inspect}" unless v1 == v2
44
+ end
45
+
46
+ puts 'test_hash'
47
+ assert_equal d.string_reference_path_to(d[:a], 3), "\"2\" is \n value of :a => \"2\" is \nassociation in {:a=>\"2\", :b=>34}"
48
+
49
+ puts 'test_superclass'
50
+ assert_equal EE.string_reference_path_to(AA, 5), "AA is \nsuperclass of BB is \nsuperclass of CC is \nsuperclass of DD is \nsuperclass of EE"
51
+
52
+ puts 'test_instance_variable'
53
+ assert_equal aa.string_reference_path_to(o, 3), "#{o.inspect} is \n@x in #{aa.inspect}"
54
+
55
+ puts 'test_class_to_inst_var'
56
+ assert_equal cc.string_reference_path_to(OO, 5), "OO is \nclass of #{o.inspect} is \n @x in #{aa.inspect} is \n @x in #{bb.inspect} is \n @x in #{cc.inspect}"
57
+
58
+ puts 'test_array'
59
+ assert_equal a.string_reference_path_to(b, 20), "[] is \nat 0 of [[]] is \nat 0 of [[[]]] is \nat 0 of [[[[]]]] is \nat 0 of [[[[[]]]]] is \nat 0 of [[[[[[]]]]]] is \nat 0 of [[[[[[[]]]]]]] is \nat 0 of [[[[[[[[]]]]]]]] is \nat 0 of [[[[[[[[[]]]]]]]]] is \nat 0 of [[[[[[[[[[]]]]]]]]]] is \nat 0 of [[[[[[[[[[[]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[]]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[[]]]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[[[]]]]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[[[[]]]]]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]] is \nat 0 of [[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]"
60
+
61
+ puts 'test_eigenclass'
62
+ assert_equal X.string_reference_path_to(x, 5), "#{x.inspect} is \neigenclass of X"
63
+
64
+ puts 'test_eigenclass_base'
65
+ assert_equal x.string_reference_path_to(X, 5), "X is \neigenbase of #{x.inspect}"
66
+
67
+ puts 'test_include'
68
+ assert_equal AA.string_reference_path_to(Mod, 5), "Mod is \nincluded by AA"
69
+
70
+ puts 'done!'
@@ -1,19 +1,32 @@
1
- require "maglev_record"
2
-
3
1
  class Book
4
- include MaglevRecord::Base
5
-
2
+ include MaglevRecord::ReadWrite
6
3
  attr_accessor :author, :title, :comments
7
-
8
- validates :author, :presence => true
9
- validates :title, :presence => true,
10
- :length => { :minimum => 5 }
11
-
12
- def to_s
13
- title
4
+ def self.example_params
5
+ { :author => "Author", :title => "Title" }
6
+ end
7
+ def self.example
8
+ self.new(example_params)
14
9
  end
10
+ end
15
11
 
16
- def self.dummy
17
- Book.new(:title => "Harry Potter and the Chamber of Secrets", :author => "Joanne K. Rowling")
12
+ class RootedBook < Book
13
+ include MaglevRecord::RootedBase
14
+ def book
15
+ puts "I am a RootedBook"
18
16
  end
19
17
  end
18
+
19
+ class UnrootedBook < Book
20
+ include MaglevRecord::Base
21
+ end
22
+
23
+ Book.maglev_record_persistable
24
+ RootedBook.maglev_record_persistable
25
+ UnrootedBook.maglev_record_persistable
26
+ Maglev.commit_transaction
27
+
28
+ class RootedBook
29
+ include ActiveModel::Validations
30
+ validates :author, :presence => true,
31
+ :length => { :minimum => 4 }
32
+ end
@@ -0,0 +1,8 @@
1
+ Migration.new(Time.utc(2013, 2, 1, 10, 0, 0, 0), "Creating a global variable $DUMMY") do
2
+ def up
3
+ $DUMMY = 1
4
+ end
5
+ def down
6
+ $DUMMY = nil
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ Migration.new(Time.utc(2014, 2, 1, 10, 0, 0, 0), "Multiplying $DUMMY by 2") do
2
+ def up
3
+ $DUMMY *= 2
4
+ end
5
+ def down
6
+ $DUMMY /= 2
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ Migration.new(Time.utc(2015, 2, 1, 10, 0, 0, 0), "Adding 1 to $DUMMY") do
2
+ def up
3
+ $DUMMY += 1
4
+ end
5
+ def down
6
+ $DUMMY -= 1
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ Migration.new(Time.utc(2013, 2, 1, 10, 0, 0, 0), "Change book title") do
2
+ def up
3
+ RootedBook.each do |book|
4
+ book.title = "A new book title"
5
+ end
6
+ end
7
+ def down
8
+ RootedBook.each do |book|
9
+ book.title = "Back to old title"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ Migration.new(Time.utc(2014, 2, 1, 10, 0, 0, 0), "Change book title again") do
2
+ def up
3
+ RootedBook.each do |book|
4
+ book.title = "A even newer book title"
5
+ end
6
+ end
7
+ def down
8
+ RootedBook.each do |book|
9
+ book.title = "A new book title"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ Migration.new(Time.utc(2015, 2, 1, 10, 0, 0, 0), "Change book title to most recent one") do
2
+ def up
3
+ RootedBook.each do |book|
4
+ book.title = "The most recent book title"
5
+ end
6
+ end
7
+ def down
8
+ RootedBook.each do |book|
9
+ book.title = "A even newer book title"
10
+ end
11
+ end
12
+ end