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,99 @@
1
+ module ActiveGraph::Shared
2
+ # TypecastedAttributes allows types to be declared for your attributes
3
+ #
4
+ # Types are declared by passing the :type option to the attribute class
5
+ # method. After a type is declared, attribute readers will convert any
6
+ # assigned attribute value to the declared type. If the assigned value
7
+ # cannot be cast, nil will be returned instead. You can access the original
8
+ # assigned value using the before_type_cast methods.
9
+ #
10
+ # See {Typecasting} for the currently supported types.
11
+ #
12
+ # @example Usage
13
+ # class Person
14
+ # include ActiveGraph::Shared::TypecastedAttributes
15
+ # attribute :age, :type => Integer
16
+ # end
17
+ #
18
+ # person = Person.new
19
+ # person.age = "29"
20
+ # person.age #=> 29
21
+ # person.age_before_type_cast #=> "29"
22
+ #
23
+ # Originally part of ActiveAttr, https://github.com/cgriego/active_attr
24
+ module TypecastedAttributes
25
+ extend ActiveSupport::Concern
26
+ include ActiveGraph::Shared::Attributes
27
+
28
+ included do
29
+ attribute_method_suffix '_before_type_cast'
30
+ end
31
+
32
+ # Read the raw attribute value
33
+ #
34
+ # @example Reading a raw age value
35
+ # person.age = "29"
36
+ # person.attribute_before_type_cast(:age) #=> "29"
37
+ #
38
+ # @param [String, Symbol, #to_s] name Attribute name
39
+ #
40
+ # @return [Object, nil] The attribute value before typecasting
41
+ def attribute_before_type_cast(name)
42
+ @attributes ||= ActiveGraph::AttributeSet.new({}, self.class.attributes.keys)
43
+ @attributes.fetch_value(name.to_s)
44
+ end
45
+
46
+ private
47
+
48
+ # Reads the attribute and typecasts the result
49
+ def attribute(name)
50
+ Property::NEO4J_DRIVER_DATA_TYPES.include?(_attribute_type(name)) ? super : typecast_attribute(_attribute_typecaster(name), super)
51
+ end
52
+
53
+ def typecast_attribute(typecaster, value)
54
+ self.class.typecast_attribute(typecaster, value)
55
+ end
56
+
57
+ # Calculates an attribute type
58
+ #
59
+ # @private
60
+ def _attribute_type(attribute_name)
61
+ self.class._attribute_type(attribute_name)
62
+ end
63
+
64
+ # Resolve an attribute typecaster
65
+ #
66
+ # @private
67
+ def _attribute_typecaster(attribute_name)
68
+ type = _attribute_type(attribute_name)
69
+ default_typecaster = self.class.attributes[attribute_name].typecaster
70
+ caster = default_typecaster || ActiveGraph::Shared::TypeConverters.typecaster_for(type)
71
+ caster || fail(ActiveGraph::UnknownTypeConverterError, "Unable to cast to type #{type}")
72
+ end
73
+
74
+ module ClassMethods
75
+ # Returns the class name plus its attribute names and types
76
+ #
77
+ # @example Inspect the model's definition.
78
+ # Person.inspect
79
+ #
80
+ # @return [String] Human-readable presentation of the attributes
81
+ def inspect
82
+ inspected_attributes = attribute_names.sort.map { |name| "#{name}: #{_attribute_type(name)}" }
83
+ attributes_list = "(#{inspected_attributes.join(', ')})" unless inspected_attributes.empty?
84
+ "#{name}#{attributes_list}"
85
+ end
86
+
87
+ # Calculates an attribute type
88
+ #
89
+ # @private
90
+ def _attribute_type(attribute_name)
91
+ attributes[attribute_name].type || Object
92
+ end
93
+
94
+ def typecast_attribute(typecaster, value)
95
+ ActiveGraph::Shared::TypeConverters.typecast_attribute(typecaster, value)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,53 @@
1
+ module ActiveGraph
2
+ module Shared
3
+ # This module provides a convenient way of registering a custom Typecasting class. Custom Typecasters all follow a simple pattern.
4
+ #
5
+ # EXAMPLE:
6
+ #
7
+ # .. code-block:: ruby
8
+ #
9
+ # class RangeConverter
10
+ # class << self
11
+ # def primitive_type
12
+ # String
13
+ # end
14
+ #
15
+ # def convert_type
16
+ # Range
17
+ # end
18
+ #
19
+ # def to_db(value)
20
+ # value.to_s
21
+ # end
22
+ #
23
+ # def to_ruby(value)
24
+ # ends = value.to_s.split('..').map { |d| Integer(d) }
25
+ # ends[0]..ends[1]
26
+ # end
27
+ # alias_method :call, :to_ruby
28
+ # end
29
+ #
30
+ # include ActiveGraph::Shared::Typecaster
31
+ # end
32
+ #
33
+ # This would allow you to use `property :my_prop, type: Range` in a model.
34
+ # Each method and the `alias_method` call is required. Make sure the module inclusion happens at the end of the file.
35
+ #
36
+ # `primitive_type` is used to fool ActiveAttr's type converters, which only recognize a few basic Ruby classes.
37
+ #
38
+ # `convert_type` must match the constant given to the `type` option.
39
+ #
40
+ # `to_db` provides logic required to transform your value into the class defined by `primitive_type`
41
+ #
42
+ # `to_ruby` provides logic to transform the DB-provided value back into the class expected by code using the property.
43
+ # In other words, it should match the `convert_type`.
44
+ #
45
+ # Note that `alias_method` is used to make `to_ruby` respond to `call`. This is to provide compatibility with ActiveAttr.
46
+
47
+ module Typecaster
48
+ def self.included(other)
49
+ ActiveGraph::Shared::TypeConverters.register_converter(other)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,44 @@
1
+ module ActiveGraph
2
+ module Shared
3
+ module Validations
4
+ extend ActiveSupport::Concern
5
+ include ActiveModel::Validations
6
+ # Implements the ActiveModel::Validation hook method.
7
+ # @see http://rubydoc.info/docs/rails/ActiveModel/Validations:read_attribute_for_validation
8
+ def read_attribute_for_validation(key)
9
+ respond_to?(key) ? send(key) : self[key]
10
+ end
11
+
12
+ # The validation process on save can be skipped by passing false. The regular Model#save method is
13
+ # replaced with this when the validations module is mixed in, which it is by default.
14
+ # @param [Hash] options the options to create a message with.
15
+ # @option options [true, false] :validate if false no validation will take place
16
+ # @return [Boolean] true if it saved it successfully
17
+ def save(options = {})
18
+ perform_validations(options) ? super : false
19
+ end
20
+
21
+ # @return [Boolean] true if valid
22
+ def valid?(context = nil)
23
+ context ||= (new_record? ? :create : :update)
24
+ super(context)
25
+ errors.empty?
26
+ end
27
+
28
+ private
29
+
30
+ def perform_validations(options = {})
31
+ perform_validation = case options
32
+ when Hash
33
+ options[:validate] != false
34
+ end
35
+
36
+ if perform_validation
37
+ valid?(options.is_a?(Hash) ? options[:context] : nil)
38
+ else
39
+ true
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,204 @@
1
+ require 'rake'
2
+ require 'active_support/concern'
3
+ require 'active_graph/migration'
4
+
5
+ if !defined?(Rails) && !Rake::Task.task_defined?('environment')
6
+ desc 'Run a script against the database to perform system-wide changes'
7
+ task :environment do
8
+ require 'active_graph/session_manager'
9
+ require 'ostruct'
10
+ neo4j_url = ENV['NEO4J_URL'] || 'http://localhost:7474'
11
+ $LOAD_PATH.unshift File.dirname('./')
12
+ ActiveGraph::Base.on_establish_driver do
13
+ Neo4j::Driver::GraphDatabase.driver(neo4j_url)
14
+ end
15
+ end
16
+ end
17
+
18
+ namespace :neo4j do
19
+ task :allow_migrations do
20
+ ActiveGraph::Migrations.currently_running_migrations = true
21
+ end
22
+ desc 'Run a script against the database to perform system-wide changes'
23
+ task :legacy_migrate, [:task_name, :subtask] => :environment do |_, args|
24
+ path = Rake.original_dir
25
+ migration_task = args[:task_name]
26
+ task_name_constant = migration_task.split('_').map(&:capitalize).join('')
27
+ begin
28
+ migration_class = "ActiveGraph::Migration::#{task_name_constant}".constantize
29
+ rescue NameError
30
+ load File.join(path, 'db', 'neo4j-migrate', "#{migration_task}.rb")
31
+ migration_class = task_name_constant.to_s.constantize
32
+ end
33
+ migration = migration_class.new(path)
34
+
35
+ subtask = args[:subtask]
36
+ if subtask
37
+ migration.send(subtask)
38
+ else
39
+ migration.migrate
40
+ end
41
+ end
42
+
43
+ desc 'A shortcut for neo4j::migrate::all'
44
+ task :migrate do
45
+ Rake::Task['neo4j:migrate:all'].invoke
46
+ end
47
+
48
+ # TODO: Make sure these tasks don't run in versions of Neo4j before 3.0
49
+ namespace :schema do
50
+ SCHEMA_YAML_PATH = 'db/neo4j/schema.yml'
51
+ SCHEMA_YAML_COMMENT = <<COMMENT
52
+ # This file is auto-generated from the current state of the database. Instead
53
+ # of editing this file, please use the migrations feature of Node to
54
+ # incrementally modify your database, and then regenerate this schema definition.
55
+ #
56
+ # Note that this schema.yml definition is the authoritative source for your
57
+ # database schema. If you need to create the application database on another
58
+ # system, you should be using neo4j:schema:load, not running all the migrations
59
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
60
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
61
+ #
62
+ # It's strongly recommended that you check this file into your version control system.
63
+
64
+ COMMENT
65
+
66
+ def check_neo4j_version_3
67
+ if ActiveGraph::Base.version > '3.0.0'
68
+ yield
69
+ else
70
+ puts 'WARNING: This task does not work for versions of Neo4j before 3.0.0'
71
+ end
72
+ end
73
+
74
+ desc 'Creates a db/neo4j/schema.yml file which represents the indexes / constraints in the Neo4j DB'
75
+ task dump: :environment do
76
+ check_neo4j_version_3 do
77
+ require 'active_graph/migrations/schema'
78
+
79
+ schema_data = ActiveGraph::Migrations::Schema.fetch_schema_data
80
+
81
+ runner = ActiveGraph::Migrations::Runner.new
82
+ schema_data[:versions] = runner.complete_migration_versions.sort
83
+
84
+ FileUtils.mkdir_p(File.dirname(SCHEMA_YAML_PATH))
85
+ File.open(SCHEMA_YAML_PATH, 'w') { |file| file << SCHEMA_YAML_COMMENT + schema_data.to_yaml }
86
+
87
+ puts "Dumped updated schema file to #{SCHEMA_YAML_PATH}"
88
+ end
89
+ end
90
+
91
+ desc "Loads a db/neo4j/schema.yml file into the database\nOptionally removes schema elements which aren't in the schema.yml file (defaults to false)"
92
+ task :load, [:remove_missing] => :environment do |_t, args|
93
+ check_neo4j_version_3 do
94
+ require 'active_graph/migrations/schema'
95
+
96
+ args.with_defaults(remove_missing: false)
97
+
98
+ schema_data = YAML.safe_load(File.read(SCHEMA_YAML_PATH), [Symbol])
99
+
100
+ ActiveGraph::Base.subscribe_to_query(&method(:puts))
101
+
102
+ ActiveGraph::Base.transaction do
103
+ ActiveGraph::Migrations::Schema.synchronize_schema_data(schema_data, args[:remove_missing])
104
+ end
105
+
106
+ ActiveGraph::Base.transaction do
107
+ runner = ActiveGraph::Migrations::Runner.new
108
+ runner.mark_versions_as_complete(schema_data[:versions]) # Run in test mode?
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ namespace :migrate do
115
+ desc 'Run all pending migrations'
116
+ task all: [:allow_migrations, :environment] do
117
+ runner = ActiveGraph::Migrations::Runner.new
118
+ runner.all
119
+
120
+ Rake::Task['neo4j:schema:dump'].invoke
121
+ end
122
+
123
+ desc 'Run a migration given its VERSION'
124
+ task up: [:allow_migrations, :environment] do
125
+ version = ENV['VERSION'] || fail(ArgumentError, 'VERSION is required')
126
+ runner = ActiveGraph::Migrations::Runner.new
127
+ runner.up version
128
+
129
+ Rake::Task['neo4j:schema:dump'].invoke
130
+ end
131
+
132
+ desc 'Revert a migration given its VERSION'
133
+ task down: [:allow_migrations, :environment] do
134
+ version = ENV['VERSION'] || fail(ArgumentError, 'VERSION is required')
135
+ runner = ActiveGraph::Migrations::Runner.new
136
+ runner.down version
137
+
138
+ Rake::Task['neo4j:schema:dump'].invoke
139
+ end
140
+
141
+ desc 'Print a report of migrations status'
142
+ task status: [:allow_migrations, :environment] do
143
+ runner = ActiveGraph::Migrations::Runner.new
144
+ runner.status
145
+ end
146
+
147
+ desc 'Resolve an incomplete version state'
148
+ task resolve: [:allow_migrations, :environment] do
149
+ version = ENV['VERSION'] || fail(ArgumentError, 'VERSION is required')
150
+ runner = ActiveGraph::Migrations::Runner.new
151
+ runner.resolve version
152
+ end
153
+
154
+ desc 'Resolve an incomplete version state'
155
+ task reset: [:allow_migrations, :environment] do
156
+ version = ENV['VERSION'] || fail(ArgumentError, 'VERSION is required')
157
+ runner = ActiveGraph::Migrations::Runner.new
158
+ runner.reset version
159
+ end
160
+ end
161
+
162
+ desc 'Rollbacks migrations given a STEP number'
163
+ task rollback: [:allow_migrations, :environment] do
164
+ steps = (ENV['STEP'] || 1).to_i
165
+ runner = ActiveGraph::Migrations::Runner.new
166
+ runner.rollback(steps)
167
+
168
+ Rake::Task['neo4j:schema:dump'].invoke
169
+ end
170
+
171
+ # Temporary to help people change to 8.0
172
+ desc 'Generates a migration for the specified constraint/index and label/property combination.'
173
+ task :generate_schema_migration, :index_or_constraint, :label, :property_name do |_t, args|
174
+ index_or_constraint, label, property_name = args.values_at(:index_or_constraint, :label, :property_name)
175
+
176
+ if !%w(index constraint).include?(index_or_constraint)
177
+ fail "Invalid schema element type: #{index_or_constraint} (should be either `index` or `constraint`)"
178
+ end
179
+ fail 'Label must be specified' if label.blank?
180
+ fail 'Property name must be specified' if property_name.blank?
181
+
182
+ migration_class_name = "ForceCreate#{label.camelize}#{property_name.camelize}#{index_or_constraint.capitalize}".gsub('::', '').underscore.camelize
183
+
184
+ require 'fileutils'
185
+ FileUtils.mkdir_p('db/neo4j/migrate')
186
+ path = File.join('db/neo4j/migrate', "#{DateTime.now.utc.strftime('%Y%m%d%H%M%S')}_#{migration_class_name.underscore}.rb")
187
+
188
+ content = <<-CONTENT
189
+ class #{migration_class_name} < ActiveGraph::Migrations::Base
190
+ def up
191
+ add_#{index_or_constraint} #{label.to_sym.inspect}, #{property_name.to_sym.inspect}, force: true
192
+ end
193
+
194
+ def down
195
+ drop_#{index_or_constraint} #{label.to_sym.inspect}, #{property_name.to_sym.inspect}
196
+ end
197
+ end
198
+ CONTENT
199
+
200
+ File.open(path, 'w') { |f| f << content }
201
+
202
+ puts "Generated #{path}"
203
+ end
204
+ end
@@ -0,0 +1,11 @@
1
+ require 'active_graph/timestamps/created'
2
+ require 'active_graph/timestamps/updated'
3
+
4
+ module ActiveGraph
5
+ # This mixin includes timestamps in the included class
6
+ module Timestamps
7
+ extend ActiveSupport::Concern
8
+ include Created
9
+ include Updated
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module ActiveGraph
2
+ module Timestamps
3
+ # This mixin includes a created_at timestamp property
4
+ module Created
5
+ extend ActiveSupport::Concern
6
+ included { property :created_at }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module ActiveGraph
2
+ module Timestamps
3
+ # This mixin includes a updated_at timestamp property
4
+ module Updated
5
+ extend ActiveSupport::Concern
6
+ included { property :updated_at }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ module ActiveGraph
2
+ module Transaction
3
+ def rollback
4
+ super
5
+ @rolled_back = true
6
+ end
7
+
8
+ def after_commit(&block)
9
+ after_commit_registry << block
10
+ end
11
+
12
+ def apply_callbacks
13
+ after_commit_registry.each(&:call) unless @rolled_back
14
+ end
15
+
16
+ private
17
+
18
+ def after_commit_registry
19
+ @after_commit_registry ||= []
20
+ end
21
+ end
22
+ end