activegraph 11.0.0.beta.1-java

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 (144) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +2016 -0
  3. data/CONTRIBUTORS +12 -0
  4. data/Gemfile +24 -0
  5. data/README.md +111 -0
  6. data/activegraph.gemspec +52 -0
  7. data/bin/rake +17 -0
  8. data/config/locales/en.yml +5 -0
  9. data/config/neo4j/add_classnames.yml +1 -0
  10. data/config/neo4j/config.yml +35 -0
  11. data/lib/active_graph.rb +123 -0
  12. data/lib/active_graph/ansi.rb +14 -0
  13. data/lib/active_graph/attribute_set.rb +32 -0
  14. data/lib/active_graph/base.rb +77 -0
  15. data/lib/active_graph/class_arguments.rb +39 -0
  16. data/lib/active_graph/config.rb +135 -0
  17. data/lib/active_graph/core.rb +14 -0
  18. data/lib/active_graph/core/connection_failed_error.rb +6 -0
  19. data/lib/active_graph/core/cypher_error.rb +37 -0
  20. data/lib/active_graph/core/entity.rb +11 -0
  21. data/lib/active_graph/core/instrumentable.rb +37 -0
  22. data/lib/active_graph/core/label.rb +135 -0
  23. data/lib/active_graph/core/logging.rb +44 -0
  24. data/lib/active_graph/core/node.rb +15 -0
  25. data/lib/active_graph/core/querable.rb +41 -0
  26. data/lib/active_graph/core/query.rb +485 -0
  27. data/lib/active_graph/core/query_builder.rb +18 -0
  28. data/lib/active_graph/core/query_clauses.rb +727 -0
  29. data/lib/active_graph/core/query_ext.rb +24 -0
  30. data/lib/active_graph/core/query_find_in_batches.rb +46 -0
  31. data/lib/active_graph/core/record.rb +51 -0
  32. data/lib/active_graph/core/result.rb +31 -0
  33. data/lib/active_graph/core/schema.rb +65 -0
  34. data/lib/active_graph/core/schema_errors.rb +12 -0
  35. data/lib/active_graph/core/wrappable.rb +30 -0
  36. data/lib/active_graph/errors.rb +59 -0
  37. data/lib/active_graph/lazy_attribute_hash.rb +38 -0
  38. data/lib/active_graph/migration.rb +148 -0
  39. data/lib/active_graph/migrations.rb +27 -0
  40. data/lib/active_graph/migrations/base.rb +77 -0
  41. data/lib/active_graph/migrations/check_pending.rb +20 -0
  42. data/lib/active_graph/migrations/helpers.rb +105 -0
  43. data/lib/active_graph/migrations/helpers/id_property.rb +72 -0
  44. data/lib/active_graph/migrations/helpers/relationships.rb +66 -0
  45. data/lib/active_graph/migrations/helpers/schema.rb +63 -0
  46. data/lib/active_graph/migrations/migration_file.rb +24 -0
  47. data/lib/active_graph/migrations/runner.rb +195 -0
  48. data/lib/active_graph/migrations/schema.rb +64 -0
  49. data/lib/active_graph/migrations/schema_migration.rb +14 -0
  50. data/lib/active_graph/model_schema.rb +139 -0
  51. data/lib/active_graph/node.rb +110 -0
  52. data/lib/active_graph/node/callbacks.rb +8 -0
  53. data/lib/active_graph/node/dependent.rb +11 -0
  54. data/lib/active_graph/node/dependent/association_methods.rb +49 -0
  55. data/lib/active_graph/node/dependent/query_proxy_methods.rb +52 -0
  56. data/lib/active_graph/node/dependent_callbacks.rb +31 -0
  57. data/lib/active_graph/node/enum.rb +26 -0
  58. data/lib/active_graph/node/has_n.rb +602 -0
  59. data/lib/active_graph/node/has_n/association.rb +278 -0
  60. data/lib/active_graph/node/has_n/association/rel_factory.rb +61 -0
  61. data/lib/active_graph/node/has_n/association/rel_wrapper.rb +23 -0
  62. data/lib/active_graph/node/has_n/association_cypher_methods.rb +108 -0
  63. data/lib/active_graph/node/id_property.rb +224 -0
  64. data/lib/active_graph/node/id_property/accessor.rb +62 -0
  65. data/lib/active_graph/node/initialize.rb +21 -0
  66. data/lib/active_graph/node/labels.rb +207 -0
  67. data/lib/active_graph/node/labels/index.rb +37 -0
  68. data/lib/active_graph/node/labels/reloading.rb +21 -0
  69. data/lib/active_graph/node/node_list_formatter.rb +13 -0
  70. data/lib/active_graph/node/node_wrapper.rb +54 -0
  71. data/lib/active_graph/node/orm_adapter.rb +82 -0
  72. data/lib/active_graph/node/persistence.rb +186 -0
  73. data/lib/active_graph/node/property.rb +60 -0
  74. data/lib/active_graph/node/query.rb +76 -0
  75. data/lib/active_graph/node/query/query_proxy.rb +367 -0
  76. data/lib/active_graph/node/query/query_proxy_eager_loading.rb +177 -0
  77. data/lib/active_graph/node/query/query_proxy_eager_loading/association_tree.rb +75 -0
  78. data/lib/active_graph/node/query/query_proxy_enumerable.rb +110 -0
  79. data/lib/active_graph/node/query/query_proxy_find_in_batches.rb +19 -0
  80. data/lib/active_graph/node/query/query_proxy_link.rb +139 -0
  81. data/lib/active_graph/node/query/query_proxy_methods.rb +303 -0
  82. data/lib/active_graph/node/query/query_proxy_methods_of_mass_updating.rb +99 -0
  83. data/lib/active_graph/node/query_methods.rb +68 -0
  84. data/lib/active_graph/node/reflection.rb +86 -0
  85. data/lib/active_graph/node/rels.rb +11 -0
  86. data/lib/active_graph/node/scope.rb +166 -0
  87. data/lib/active_graph/node/unpersisted.rb +48 -0
  88. data/lib/active_graph/node/validations.rb +59 -0
  89. data/lib/active_graph/paginated.rb +27 -0
  90. data/lib/active_graph/railtie.rb +108 -0
  91. data/lib/active_graph/relationship.rb +68 -0
  92. data/lib/active_graph/relationship/callbacks.rb +21 -0
  93. data/lib/active_graph/relationship/initialize.rb +28 -0
  94. data/lib/active_graph/relationship/persistence.rb +133 -0
  95. data/lib/active_graph/relationship/persistence/query_factory.rb +95 -0
  96. data/lib/active_graph/relationship/property.rb +92 -0
  97. data/lib/active_graph/relationship/query.rb +99 -0
  98. data/lib/active_graph/relationship/rel_wrapper.rb +31 -0
  99. data/lib/active_graph/relationship/related_node.rb +87 -0
  100. data/lib/active_graph/relationship/types.rb +80 -0
  101. data/lib/active_graph/relationship/validations.rb +8 -0
  102. data/lib/active_graph/schema/operation.rb +102 -0
  103. data/lib/active_graph/shared.rb +48 -0
  104. data/lib/active_graph/shared/attributes.rb +217 -0
  105. data/lib/active_graph/shared/callbacks.rb +66 -0
  106. data/lib/active_graph/shared/cypher.rb +37 -0
  107. data/lib/active_graph/shared/declared_properties.rb +204 -0
  108. data/lib/active_graph/shared/declared_property.rb +109 -0
  109. data/lib/active_graph/shared/declared_property/index.rb +37 -0
  110. data/lib/active_graph/shared/enum.rb +167 -0
  111. data/lib/active_graph/shared/filtered_hash.rb +79 -0
  112. data/lib/active_graph/shared/identity.rb +34 -0
  113. data/lib/active_graph/shared/initialize.rb +65 -0
  114. data/lib/active_graph/shared/marshal.rb +23 -0
  115. data/lib/active_graph/shared/mass_assignment.rb +63 -0
  116. data/lib/active_graph/shared/permitted_attributes.rb +28 -0
  117. data/lib/active_graph/shared/persistence.rb +272 -0
  118. data/lib/active_graph/shared/property.rb +249 -0
  119. data/lib/active_graph/shared/query_factory.rb +122 -0
  120. data/lib/active_graph/shared/rel_type_converters.rb +43 -0
  121. data/lib/active_graph/shared/serialized_properties.rb +30 -0
  122. data/lib/active_graph/shared/type_converters.rb +439 -0
  123. data/lib/active_graph/shared/typecasted_attributes.rb +99 -0
  124. data/lib/active_graph/shared/typecaster.rb +53 -0
  125. data/lib/active_graph/shared/validations.rb +44 -0
  126. data/lib/active_graph/tasks/migration.rake +204 -0
  127. data/lib/active_graph/timestamps.rb +11 -0
  128. data/lib/active_graph/timestamps/created.rb +9 -0
  129. data/lib/active_graph/timestamps/updated.rb +9 -0
  130. data/lib/active_graph/transaction.rb +22 -0
  131. data/lib/active_graph/transactions.rb +57 -0
  132. data/lib/active_graph/type_converters.rb +7 -0
  133. data/lib/active_graph/undeclared_properties.rb +53 -0
  134. data/lib/active_graph/version.rb +3 -0
  135. data/lib/active_graph/wrapper.rb +4 -0
  136. data/lib/rails/generators/active_graph/migration/migration_generator.rb +16 -0
  137. data/lib/rails/generators/active_graph/migration/templates/migration.erb +9 -0
  138. data/lib/rails/generators/active_graph/model/model_generator.rb +89 -0
  139. data/lib/rails/generators/active_graph/model/templates/migration.erb +11 -0
  140. data/lib/rails/generators/active_graph/model/templates/model.erb +15 -0
  141. data/lib/rails/generators/active_graph/upgrade_v8/templates/migration.erb +17 -0
  142. data/lib/rails/generators/active_graph/upgrade_v8/upgrade_v8_generator.rb +34 -0
  143. data/lib/rails/generators/active_graph_generator.rb +121 -0
  144. metadata +423 -0
@@ -0,0 +1,27 @@
1
+ module ActiveGraph
2
+ module Migrations
3
+ extend ActiveSupport::Autoload
4
+ autoload :Helpers
5
+ autoload :MigrationFile
6
+ autoload :Base
7
+ autoload :Runner
8
+ autoload :SchemaMigration
9
+ autoload :CheckPending
10
+
11
+ class << self
12
+ def check_for_pending_migrations!
13
+ return if ActiveGraph::Config.configuration['skip_migration_check']
14
+
15
+ runner = ActiveGraph::Migrations::Runner.new
16
+ pending = runner.pending_migrations
17
+ fail ::ActiveGraph::PendingMigrationError, pending if pending.any?
18
+ end
19
+
20
+ attr_accessor :currently_running_migrations
21
+
22
+ def maintain_test_schema!
23
+ ActiveGraph::Migrations::Runner.new(silenced: true).all
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,77 @@
1
+ module ActiveGraph
2
+ module Migrations
3
+ class Base
4
+ include ActiveGraph::Migrations::Helpers
5
+ include ActiveGraph::Migrations::Helpers::Schema
6
+ include ActiveGraph::Migrations::Helpers::IdProperty
7
+ include ActiveGraph::Migrations::Helpers::Relationships
8
+
9
+ def initialize(migration_id, options = {})
10
+ @migration_id = migration_id
11
+ @silenced = options[:silenced]
12
+ end
13
+
14
+ def migrate(method)
15
+ Benchmark.realtime do
16
+ method == :up ? migrate_up : migrate_down
17
+ end
18
+ end
19
+
20
+ def up
21
+ fail NotImplementedError
22
+ end
23
+
24
+ def down
25
+ fail NotImplementedError
26
+ end
27
+
28
+ private
29
+
30
+ def migrate_up
31
+ schema = SchemaMigration.create!(migration_id: @migration_id, incomplete: true)
32
+ begin
33
+ run_migration(:up)
34
+ rescue StandardError => e
35
+ schema.destroy if transactions?
36
+ handle_migration_error!(e)
37
+ else
38
+ schema.update!(incomplete: nil)
39
+ end
40
+ end
41
+
42
+ def migrate_down
43
+ schema = SchemaMigration.find_by!(migration_id: @migration_id)
44
+ schema.update!(incomplete: true)
45
+ begin
46
+ run_migration(:down)
47
+ rescue StandardError => e
48
+ schema.update!(incomplete: nil) if transactions?
49
+ handle_migration_error!(e)
50
+ else
51
+ schema.destroy
52
+ end
53
+ end
54
+
55
+ def run_migration(direction)
56
+ migration_transaction { log_queries { public_send(direction) } }
57
+ end
58
+
59
+ def handle_migration_error!(e)
60
+ fail e unless e.message =~ /Cannot perform data updates in a transaction that has performed schema updates./
61
+ fail MigrationError,
62
+ "#{e.message}. Please add `disable_transactions!` in your migration file."
63
+ end
64
+
65
+ def migration_transaction(&block)
66
+ transactions? ? ActiveGraph::Base.transaction(&block) : block.call
67
+ end
68
+
69
+ def log_queries
70
+ subscriber = ActiveGraph::Base.subscribe_to_query(&method(:output))
71
+ yield
72
+ ensure
73
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,20 @@
1
+ module ActiveGraph
2
+ module Migrations
3
+ class CheckPending
4
+ def initialize(app)
5
+ @app = app
6
+ @last_check = 0
7
+ end
8
+
9
+ def call(env)
10
+ latest_migration = ActiveGraph::Migrations::Runner.latest_migration
11
+ mtime = latest_migration ? latest_migration.version.to_i : 0
12
+ if @last_check < mtime
13
+ ActiveGraph::Migrations.check_for_pending_migrations!
14
+ @last_check = mtime
15
+ end
16
+ @app.call(env)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,105 @@
1
+ require 'benchmark'
2
+
3
+ module ActiveGraph
4
+ module Migrations
5
+ module Helpers
6
+ extend ActiveSupport::Concern
7
+ extend ActiveSupport::Autoload
8
+
9
+ autoload :Schema
10
+ autoload :IdProperty
11
+ autoload :Relationships
12
+
13
+ PROPERTY_ALREADY_DEFINED = 'Property `%{new_property}` is already defined in `%{label}`. '\
14
+ 'To overwrite, call `remove_property(:%{label}, :%{new_property})` before this method.'.freeze
15
+
16
+ def remove_property(label, property)
17
+ by_label(label).remove("n.#{property}").exec
18
+ end
19
+
20
+ def rename_property(label, old_property, new_property)
21
+ fail ActiveGraph::MigrationError, format(PROPERTY_ALREADY_DEFINED, new_property: new_property, label: label) if property_exists?(label, new_property)
22
+ by_label(label).set("n.#{new_property} = n.#{old_property}")
23
+ .remove("n.#{old_property}").exec
24
+ end
25
+
26
+ def drop_nodes(label)
27
+ query.match(n: label)
28
+ .optional_match('(n)-[r]-()')
29
+ .delete(:r, :n).exec
30
+ end
31
+
32
+ def add_labels(label, new_labels)
33
+ by_label(label).set(n: new_labels).exec
34
+ end
35
+
36
+ def add_label(label, new_label)
37
+ add_labels(label, [new_label])
38
+ end
39
+
40
+ def remove_labels(label, labels_to_remove)
41
+ by_label(label).remove(n: labels_to_remove).exec
42
+ end
43
+
44
+ def remove_label(label, label_to_remove)
45
+ remove_labels(label, [label_to_remove])
46
+ end
47
+
48
+ def rename_label(old_label, new_label)
49
+ by_label(old_label).set(n: new_label).remove(n: old_label).exec
50
+ end
51
+
52
+ def execute(string, params = {})
53
+ ActiveGraph::Base.query(string, params).to_a
54
+ end
55
+
56
+ def say_with_time(message)
57
+ say(message)
58
+ result = nil
59
+ time = Benchmark.measure { result = yield }
60
+ say format('%.4fs', time.real), :subitem
61
+ say("#{result} rows", :subitem) if result.is_a?(Integer)
62
+ result
63
+ end
64
+
65
+ def say(message, subitem = false)
66
+ output "#{subitem ? ' ->' : '--'} #{message}"
67
+ end
68
+
69
+ def query(*args)
70
+ ActiveGraph::Base.new_query(*args)
71
+ end
72
+
73
+ protected
74
+
75
+ def output(*string_format)
76
+ puts format(*string_format) unless @silenced
77
+ end
78
+
79
+ def transactions?
80
+ self.class.transaction?
81
+ end
82
+
83
+ private
84
+
85
+ def property_exists?(label, property)
86
+ by_label(label).where("EXISTS(n.#{property})").return(:n).any?
87
+ end
88
+
89
+ def by_label(label, options = {})
90
+ symbol = options[:symbol] || :n
91
+ query.match(symbol => label)
92
+ end
93
+
94
+ module ClassMethods
95
+ def disable_transactions!
96
+ @disable_transactions = true
97
+ end
98
+
99
+ def transaction?
100
+ !@disable_transactions
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,72 @@
1
+ module ActiveGraph
2
+ module Migrations
3
+ module Helpers
4
+ module IdProperty
5
+ extend ActiveSupport::Concern
6
+
7
+ def populate_id_property(label)
8
+ model = label.to_s.constantize
9
+ max_per_batch = (ENV['MAX_PER_BATCH'] || default_max_per_batch).to_i
10
+
11
+ last_time_taken = nil
12
+
13
+ until (nodes_left = idless_count(label, model.primary_key)) == 0
14
+ print_status(last_time_taken, max_per_batch, nodes_left)
15
+
16
+ count = [nodes_left, max_per_batch].min
17
+ last_time_taken = Benchmark.realtime do
18
+ max_per_batch = id_batch_set(label, model.primary_key, Array.new(count) { new_id_for(model) }, count)
19
+ end
20
+ end
21
+ end
22
+
23
+ protected
24
+
25
+ def idless_count(label, id_property)
26
+ query.match(n: label).where("NOT EXISTS(n.#{id_property})").pluck('COUNT(n) AS ids').first
27
+ end
28
+
29
+ def id_batch_set(label, id_property, new_ids, count)
30
+ ActiveGraph::Base.transaction do
31
+ execute("MATCH (n:`#{label}`) WHERE NOT EXISTS(n.#{id_property})
32
+ with COLLECT(n) as nodes, #{new_ids} as ids
33
+ FOREACH(i in range(0,#{count - 1})|
34
+ FOREACH(node in [nodes[i]]|
35
+ SET node.#{id_property} = ids[i]))
36
+ RETURN distinct(true)
37
+ LIMIT #{count}")
38
+ count
39
+ end
40
+ rescue ActiveGraph::Server::CypherResponse::ResponseError
41
+ new_max_per_batch = (max_per_batch * 0.8).round
42
+ output "Error querying #{max_per_batch} nodes. Trying #{new_max_per_batch}"
43
+ new_max_per_batch
44
+ end
45
+
46
+ def print_status(last_time_taken, max_per_batch, nodes_left)
47
+ time_per_node = last_time_taken / max_per_batch if last_time_taken
48
+ message = if time_per_node
49
+ eta_seconds = (nodes_left * time_per_node).round
50
+ "#{nodes_left} nodes left. Last batch: #{(time_per_node * 1000.0).round(1)}ms / node (ETA: #{eta_seconds / 60} minutes)"
51
+ else
52
+ 'Running first batch...'
53
+ end
54
+
55
+ output message
56
+ end
57
+
58
+ def default_max_per_batch
59
+ 900
60
+ end
61
+
62
+ def new_id_for(model)
63
+ if model.id_property_info[:type][:auto]
64
+ SecureRandom.uuid
65
+ else
66
+ model.new.send(model.id_property_info[:type][:on])
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,66 @@
1
+ module ActiveGraph
2
+ module Migrations
3
+ module Helpers
4
+ module Relationships
5
+ extend ActiveSupport::Concern
6
+
7
+ DEFAULT_MAX_PER_BATCH = 1000
8
+
9
+ def change_relations_style(relationships, old_style, new_style, params = {})
10
+ relationships.each do |rel|
11
+ relabel_relation(relationship_style(rel, old_style), relationship_style(rel, new_style), params)
12
+ end
13
+ end
14
+
15
+ def relabel_relation(old_name, new_name, params = {})
16
+ relation_query = match_relation(old_name, params)
17
+
18
+ max_per_batch = (ENV['MAX_PER_BATCH'] || DEFAULT_MAX_PER_BATCH).to_i
19
+
20
+ count = count_relations(relation_query)
21
+ output "Indexing #{count} #{old_name}s into #{new_name}..."
22
+ while count > 0
23
+ relation_query.create("(a)-[r2:`#{new_name}`]->(b)").set('r2 = r').with(:r).limit(max_per_batch).delete(:r).exec
24
+ count = count_relations(relation_query)
25
+ output "... #{count} #{old_name}'s left to go.." if count > 0
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def match_relation(label, params = {})
32
+ from = params[:from] ? "(a:`#{params[:from]}`)" : '(a)'
33
+ to = params[:to] ? "(b:`#{params[:to]}`)" : '(b)'
34
+ relation = arrow_cypher(label, params[:direction])
35
+
36
+ query.match("#{from}#{relation}#{to}")
37
+ end
38
+
39
+ def arrow_cypher(label, direction)
40
+ case direction
41
+ when :in
42
+ "<-[r:`#{label}`]-"
43
+ when :both
44
+ "<-[r:`#{label}`]->"
45
+ else
46
+ "-[r:`#{label}`]->"
47
+ end
48
+ end
49
+
50
+ def count_relations(query)
51
+ query.pluck('COUNT(r)').first
52
+ end
53
+
54
+ def relationship_style(relationship, format)
55
+ case format.to_s
56
+ when 'lower_hashtag' then "##{relationship.downcase}"
57
+ when 'lower' then relationship.downcase
58
+ when 'upper' then relationship.upcase
59
+ else
60
+ fail("Invalid relationship type style `#{format}`.")
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,63 @@
1
+ module ActiveGraph
2
+ module Migrations
3
+ module Helpers
4
+ module Schema
5
+ extend ActiveSupport::Concern
6
+ MISSING_CONSTRAINT_OR_INDEX = 'No such %{type} for %{label}#%{property}'.freeze
7
+ DUPLICATE_CONSTRAINT_OR_INDEX = 'Duplicate %{type} for %{label}#%{property}'.freeze
8
+
9
+ def add_constraint(label, property, options = {})
10
+ force = options[:force] || false
11
+ type = options[:type] || :uniqueness
12
+ label_object = ActiveGraph::Base.label_object(label)
13
+ if label_object.constraint?(property)
14
+ if force
15
+ label_object.drop_constraint(property, type: type)
16
+ else
17
+ fail_duplicate_constraint_or_index!(:constraint, label, property)
18
+ end
19
+ end
20
+ label_object.create_constraint(property, type: type)
21
+ end
22
+
23
+ def add_index(label, property, options = {})
24
+ force = options[:force] || false
25
+ label_object = ActiveGraph::Base.label_object(label)
26
+ if label_object.index?(property)
27
+ if force
28
+ label_object.drop_index(property)
29
+ else
30
+ fail_duplicate_constraint_or_index!(:index, label, property)
31
+ end
32
+ end
33
+ label_object.create_index(property)
34
+ end
35
+
36
+ def drop_constraint(label, property, options = {})
37
+ type = options[:type] || :uniqueness
38
+ label_object = ActiveGraph::Base.label_object(label)
39
+ fail_missing_constraint_or_index!(:constraint, label, property) if !options[:force] && !label_object.constraint?(property)
40
+ label_object.drop_constraint(property, type: type)
41
+ end
42
+
43
+ def drop_index(label, property, options = {})
44
+ label_object = ActiveGraph::Base.label_object(label)
45
+ fail_missing_constraint_or_index!(:index, label, property) if !options[:force] && !label_object.index?(property)
46
+ label_object.drop_index(property)
47
+ end
48
+
49
+ protected
50
+
51
+ def fail_missing_constraint_or_index!(type, label, property)
52
+ fail ActiveGraph::MigrationError,
53
+ format(MISSING_CONSTRAINT_OR_INDEX, type: type, label: label, property: property)
54
+ end
55
+
56
+ def fail_duplicate_constraint_or_index!(type, label, property)
57
+ fail ActiveGraph::MigrationError,
58
+ format(DUPLICATE_CONSTRAINT_OR_INDEX, type: type, label: label, property: property)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,24 @@
1
+ module ActiveGraph
2
+ module Migrations
3
+ class MigrationFile
4
+ attr_reader :file_name, :symbol_name, :class_name, :version
5
+
6
+ def initialize(file_name)
7
+ @file_name = file_name
8
+ extract_data!
9
+ end
10
+
11
+ def create(options = {})
12
+ require @file_name
13
+ class_name.constantize.new(@version, options)
14
+ end
15
+
16
+ private
17
+
18
+ def extract_data!
19
+ @version, @symbol_name = File.basename(@file_name, '.rb').split('_', 2)
20
+ @class_name = @symbol_name.camelize
21
+ end
22
+ end
23
+ end
24
+ end