activegraph 10.0.0.pre.alpha.6

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 (142) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1989 -0
  3. data/CONTRIBUTORS +12 -0
  4. data/Gemfile +24 -0
  5. data/README.md +107 -0
  6. data/bin/rake +17 -0
  7. data/config/locales/en.yml +5 -0
  8. data/config/neo4j/add_classnames.yml +1 -0
  9. data/config/neo4j/config.yml +38 -0
  10. data/lib/neo4j.rb +116 -0
  11. data/lib/neo4j/active_base.rb +89 -0
  12. data/lib/neo4j/active_node.rb +108 -0
  13. data/lib/neo4j/active_node/callbacks.rb +8 -0
  14. data/lib/neo4j/active_node/dependent.rb +11 -0
  15. data/lib/neo4j/active_node/dependent/association_methods.rb +49 -0
  16. data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +51 -0
  17. data/lib/neo4j/active_node/enum.rb +26 -0
  18. data/lib/neo4j/active_node/has_n.rb +612 -0
  19. data/lib/neo4j/active_node/has_n/association.rb +278 -0
  20. data/lib/neo4j/active_node/has_n/association/rel_factory.rb +61 -0
  21. data/lib/neo4j/active_node/has_n/association/rel_wrapper.rb +23 -0
  22. data/lib/neo4j/active_node/has_n/association_cypher_methods.rb +108 -0
  23. data/lib/neo4j/active_node/id_property.rb +224 -0
  24. data/lib/neo4j/active_node/id_property/accessor.rb +62 -0
  25. data/lib/neo4j/active_node/initialize.rb +21 -0
  26. data/lib/neo4j/active_node/labels.rb +207 -0
  27. data/lib/neo4j/active_node/labels/index.rb +37 -0
  28. data/lib/neo4j/active_node/labels/reloading.rb +21 -0
  29. data/lib/neo4j/active_node/node_list_formatter.rb +13 -0
  30. data/lib/neo4j/active_node/node_wrapper.rb +54 -0
  31. data/lib/neo4j/active_node/orm_adapter.rb +82 -0
  32. data/lib/neo4j/active_node/persistence.rb +187 -0
  33. data/lib/neo4j/active_node/property.rb +60 -0
  34. data/lib/neo4j/active_node/query.rb +76 -0
  35. data/lib/neo4j/active_node/query/query_proxy.rb +374 -0
  36. data/lib/neo4j/active_node/query/query_proxy_eager_loading.rb +177 -0
  37. data/lib/neo4j/active_node/query/query_proxy_eager_loading/association_tree.rb +75 -0
  38. data/lib/neo4j/active_node/query/query_proxy_enumerable.rb +110 -0
  39. data/lib/neo4j/active_node/query/query_proxy_find_in_batches.rb +19 -0
  40. data/lib/neo4j/active_node/query/query_proxy_link.rb +139 -0
  41. data/lib/neo4j/active_node/query/query_proxy_methods.rb +302 -0
  42. data/lib/neo4j/active_node/query/query_proxy_methods_of_mass_updating.rb +86 -0
  43. data/lib/neo4j/active_node/query_methods.rb +68 -0
  44. data/lib/neo4j/active_node/reflection.rb +86 -0
  45. data/lib/neo4j/active_node/rels.rb +11 -0
  46. data/lib/neo4j/active_node/scope.rb +166 -0
  47. data/lib/neo4j/active_node/unpersisted.rb +48 -0
  48. data/lib/neo4j/active_node/validations.rb +59 -0
  49. data/lib/neo4j/active_rel.rb +67 -0
  50. data/lib/neo4j/active_rel/callbacks.rb +15 -0
  51. data/lib/neo4j/active_rel/initialize.rb +28 -0
  52. data/lib/neo4j/active_rel/persistence.rb +134 -0
  53. data/lib/neo4j/active_rel/persistence/query_factory.rb +95 -0
  54. data/lib/neo4j/active_rel/property.rb +95 -0
  55. data/lib/neo4j/active_rel/query.rb +101 -0
  56. data/lib/neo4j/active_rel/rel_wrapper.rb +31 -0
  57. data/lib/neo4j/active_rel/related_node.rb +87 -0
  58. data/lib/neo4j/active_rel/types.rb +82 -0
  59. data/lib/neo4j/active_rel/validations.rb +8 -0
  60. data/lib/neo4j/ansi.rb +14 -0
  61. data/lib/neo4j/class_arguments.rb +39 -0
  62. data/lib/neo4j/config.rb +135 -0
  63. data/lib/neo4j/core.rb +14 -0
  64. data/lib/neo4j/core/connection_failed_error.rb +6 -0
  65. data/lib/neo4j/core/cypher_error.rb +37 -0
  66. data/lib/neo4j/core/driver.rb +66 -0
  67. data/lib/neo4j/core/has_uri.rb +63 -0
  68. data/lib/neo4j/core/instrumentable.rb +36 -0
  69. data/lib/neo4j/core/label.rb +158 -0
  70. data/lib/neo4j/core/logging.rb +44 -0
  71. data/lib/neo4j/core/node.rb +23 -0
  72. data/lib/neo4j/core/querable.rb +88 -0
  73. data/lib/neo4j/core/query.rb +487 -0
  74. data/lib/neo4j/core/query_builder.rb +32 -0
  75. data/lib/neo4j/core/query_clauses.rb +727 -0
  76. data/lib/neo4j/core/query_ext.rb +24 -0
  77. data/lib/neo4j/core/query_find_in_batches.rb +49 -0
  78. data/lib/neo4j/core/relationship.rb +13 -0
  79. data/lib/neo4j/core/responses.rb +50 -0
  80. data/lib/neo4j/core/result.rb +33 -0
  81. data/lib/neo4j/core/schema.rb +30 -0
  82. data/lib/neo4j/core/schema_errors.rb +12 -0
  83. data/lib/neo4j/core/wrappable.rb +30 -0
  84. data/lib/neo4j/errors.rb +57 -0
  85. data/lib/neo4j/migration.rb +148 -0
  86. data/lib/neo4j/migrations.rb +27 -0
  87. data/lib/neo4j/migrations/base.rb +77 -0
  88. data/lib/neo4j/migrations/check_pending.rb +20 -0
  89. data/lib/neo4j/migrations/helpers.rb +105 -0
  90. data/lib/neo4j/migrations/helpers/id_property.rb +75 -0
  91. data/lib/neo4j/migrations/helpers/relationships.rb +66 -0
  92. data/lib/neo4j/migrations/helpers/schema.rb +51 -0
  93. data/lib/neo4j/migrations/migration_file.rb +24 -0
  94. data/lib/neo4j/migrations/runner.rb +195 -0
  95. data/lib/neo4j/migrations/schema.rb +44 -0
  96. data/lib/neo4j/migrations/schema_migration.rb +14 -0
  97. data/lib/neo4j/model_schema.rb +139 -0
  98. data/lib/neo4j/paginated.rb +27 -0
  99. data/lib/neo4j/railtie.rb +105 -0
  100. data/lib/neo4j/schema/operation.rb +102 -0
  101. data/lib/neo4j/shared.rb +60 -0
  102. data/lib/neo4j/shared/attributes.rb +216 -0
  103. data/lib/neo4j/shared/callbacks.rb +68 -0
  104. data/lib/neo4j/shared/cypher.rb +37 -0
  105. data/lib/neo4j/shared/declared_properties.rb +204 -0
  106. data/lib/neo4j/shared/declared_property.rb +109 -0
  107. data/lib/neo4j/shared/declared_property/index.rb +37 -0
  108. data/lib/neo4j/shared/enum.rb +167 -0
  109. data/lib/neo4j/shared/filtered_hash.rb +79 -0
  110. data/lib/neo4j/shared/identity.rb +34 -0
  111. data/lib/neo4j/shared/initialize.rb +64 -0
  112. data/lib/neo4j/shared/marshal.rb +23 -0
  113. data/lib/neo4j/shared/mass_assignment.rb +64 -0
  114. data/lib/neo4j/shared/permitted_attributes.rb +28 -0
  115. data/lib/neo4j/shared/persistence.rb +282 -0
  116. data/lib/neo4j/shared/property.rb +240 -0
  117. data/lib/neo4j/shared/query_factory.rb +102 -0
  118. data/lib/neo4j/shared/rel_type_converters.rb +43 -0
  119. data/lib/neo4j/shared/serialized_properties.rb +30 -0
  120. data/lib/neo4j/shared/type_converters.rb +433 -0
  121. data/lib/neo4j/shared/typecasted_attributes.rb +98 -0
  122. data/lib/neo4j/shared/typecaster.rb +53 -0
  123. data/lib/neo4j/shared/validations.rb +44 -0
  124. data/lib/neo4j/tasks/migration.rake +202 -0
  125. data/lib/neo4j/timestamps.rb +11 -0
  126. data/lib/neo4j/timestamps/created.rb +9 -0
  127. data/lib/neo4j/timestamps/updated.rb +9 -0
  128. data/lib/neo4j/transaction.rb +139 -0
  129. data/lib/neo4j/type_converters.rb +7 -0
  130. data/lib/neo4j/undeclared_properties.rb +53 -0
  131. data/lib/neo4j/version.rb +3 -0
  132. data/lib/neo4j/wrapper.rb +4 -0
  133. data/lib/rails/generators/neo4j/migration/migration_generator.rb +14 -0
  134. data/lib/rails/generators/neo4j/migration/templates/migration.erb +9 -0
  135. data/lib/rails/generators/neo4j/model/model_generator.rb +88 -0
  136. data/lib/rails/generators/neo4j/model/templates/migration.erb +9 -0
  137. data/lib/rails/generators/neo4j/model/templates/model.erb +15 -0
  138. data/lib/rails/generators/neo4j/upgrade_v8/templates/migration.erb +17 -0
  139. data/lib/rails/generators/neo4j/upgrade_v8/upgrade_v8_generator.rb +32 -0
  140. data/lib/rails/generators/neo4j_generator.rb +119 -0
  141. data/neo4j.gemspec +51 -0
  142. metadata +421 -0
@@ -0,0 +1,102 @@
1
+ module Neo4j
2
+ module Schema
3
+ class Operation
4
+ attr_reader :label, :property, :options
5
+
6
+ def initialize(label, property, options = default_options)
7
+ @label = if label.is_a?(Neo4j::Core::Label)
8
+ label
9
+ else
10
+ Neo4j::Core::Label.new(label)
11
+ end
12
+
13
+ @property = property.to_sym
14
+ @options = options
15
+ end
16
+
17
+ def self.incompatible_operation_classes
18
+ []
19
+ end
20
+
21
+ def label_object
22
+ label
23
+ end
24
+
25
+ def create!
26
+ drop_incompatible!
27
+ return if exist?
28
+ schema_query(:"create_#{type}")
29
+ end
30
+
31
+ def incompatible_operation_classes
32
+ self.class.incompatible_operation_classes
33
+ end
34
+
35
+ def drop!
36
+ schema_query(:"drop_#{type}")
37
+ end
38
+
39
+ def drop_incompatible!
40
+ incompatible_operation_classes.each do |clazz|
41
+ operation = clazz.new(@label, property)
42
+ operation.drop! if operation.exist?
43
+ end
44
+ end
45
+
46
+ def exist?
47
+ fail 'Abstract class, not implemented'
48
+ end
49
+
50
+ def default_options
51
+ {}
52
+ end
53
+
54
+ def type
55
+ fail 'Abstract class, not implemented'
56
+ end
57
+
58
+ private
59
+
60
+ def schema_query(method)
61
+ label.send(method, property, options)
62
+ end
63
+ end
64
+
65
+ class ExactIndexOperation < Neo4j::Schema::Operation
66
+ def self.incompatible_operation_classes
67
+ [UniqueConstraintOperation]
68
+ end
69
+
70
+ def type
71
+ 'index'
72
+ end
73
+
74
+ def exist?
75
+ label.index?(property)
76
+ end
77
+ end
78
+
79
+ class UniqueConstraintOperation < Neo4j::Schema::Operation
80
+ def self.incompatible_operation_classes
81
+ [ExactIndexOperation]
82
+ end
83
+
84
+ def type
85
+ 'uniqueness_constraint'
86
+ end
87
+
88
+ def create!
89
+ return if exist?
90
+ super
91
+ end
92
+
93
+ def exist?
94
+ label.uniqueness_constraint?(property)
95
+ end
96
+
97
+ def default_options
98
+ {type: :unique}
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,60 @@
1
+ module Neo4j
2
+ module Shared
3
+ extend ActiveSupport::Concern
4
+ extend ActiveModel::Naming
5
+
6
+ include ActiveModel::Conversion
7
+ begin
8
+ include ActiveModel::Serializers::Xml
9
+ rescue NameError; end # rubocop:disable Lint/HandleExceptions
10
+ include ActiveModel::Serializers::JSON
11
+
12
+ module ClassMethods
13
+ # TODO: Deprecate neo4j_session_name(name)
14
+
15
+ # remove?
16
+ def neo4j_session
17
+ Neo4j::ActiveBase.current_driver
18
+ end
19
+
20
+ # remove?
21
+ def current_transaction
22
+ Neo4j::ActiveBase.current_transaction
23
+ end
24
+
25
+ # This should be used everywhere. Should make it easy
26
+ # to support a session-per-model system
27
+ def neo4j_query(*args)
28
+ Neo4j::ActiveBase.query(*args)
29
+ end
30
+
31
+ def new_query
32
+ Neo4j::ActiveBase.new_query
33
+ end
34
+ end
35
+
36
+ included do
37
+ self.include_root_in_json = Neo4j::Config.include_root_in_json
38
+ @_declared_properties ||= Neo4j::Shared::DeclaredProperties.new(self)
39
+
40
+ def self.i18n_scope
41
+ :neo4j
42
+ end
43
+
44
+ def self.inherited(other)
45
+ attributes.each_pair do |k, v|
46
+ other.inherit_property k.to_sym, v.clone, declared_properties[k].options
47
+ end
48
+ super
49
+ end
50
+ end
51
+
52
+ def declared_properties
53
+ self.class.declared_properties
54
+ end
55
+
56
+ def neo4j_query(*args)
57
+ self.class.neo4j_query(*args)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,216 @@
1
+ module Neo4j::Shared
2
+ # Attributes provides a set of class methods for defining an attributes
3
+ # schema and instance methods for reading and writing attributes.
4
+ #
5
+ # @example Usage
6
+ # class Person
7
+ # include Neo4j::Shared::Attributes
8
+ # attribute :name
9
+ # end
10
+ #
11
+ # person = Person.new
12
+ # person.name = "Ben Poweski"
13
+ #
14
+ # Originally part of ActiveAttr, https://github.com/cgriego/active_attr
15
+ module Attributes
16
+ extend ActiveSupport::Concern
17
+ include ActiveModel::AttributeMethods
18
+
19
+ # Methods deprecated on the Object class which can be safely overridden
20
+ DEPRECATED_OBJECT_METHODS = %w(id type)
21
+
22
+ included do
23
+ attribute_method_suffix '' if attribute_method_matchers.none? { |matcher| matcher.prefix == '' && matcher.suffix == '' }
24
+ attribute_method_suffix '='
25
+ attribute_method_suffix '?'
26
+ end
27
+
28
+ # Performs equality checking on the result of attributes and its type.
29
+ #
30
+ # @example Compare for equality.
31
+ # model == other
32
+ #
33
+ # @param [ActiveAttr::Attributes, Object] other The other model to compare
34
+ #
35
+ # @return [true, false] True if attributes are equal and other is instance
36
+ # of the same Class, false if not.
37
+ def ==(other)
38
+ return false unless other.instance_of? self.class
39
+ attributes == other.attributes
40
+ end
41
+
42
+ # Returns a Hash of all attributes
43
+ #
44
+ # @example Get attributes
45
+ # person.attributes # => {"name"=>"Ben Poweski"}
46
+ #
47
+ # @return [Hash{String => Object}] The Hash of all attributes
48
+ def attributes
49
+ attributes_map { |name| send name }
50
+ end
51
+
52
+ # Write a single attribute to the model's attribute hash.
53
+ #
54
+ # @example Write the attribute with write_attribute
55
+ # person.write_attribute(:name, "Benjamin")
56
+ # @example Write an attribute with bracket syntax
57
+ # person[:name] = "Benjamin"
58
+ #
59
+ # @param [String, Symbol, #to_s] name The name of the attribute to update.
60
+ # @param [Object] value The value to set for the attribute.
61
+ #
62
+ # @raise [UnknownAttributeError] if the attribute is unknown
63
+ def write_attribute(name, value)
64
+ fail Neo4j::UnknownAttributeError, "unknown attribute: #{name}" if !respond_to? "#{name}="
65
+
66
+ send "#{name}=", value
67
+ end
68
+ alias []= write_attribute
69
+
70
+ def query_attribute(name)
71
+ fail Neo4j::UnknownAttributeError, "unknown attribute: #{name}" if !respond_to? "#{name}?"
72
+
73
+ send "#{name}?"
74
+ end
75
+
76
+ private
77
+
78
+ # Read an attribute from the attributes hash
79
+ def attribute(name)
80
+ @attributes ||= {}
81
+ @attributes[name]
82
+ end
83
+
84
+ # Write an attribute to the attributes hash
85
+ def attribute=(name, value)
86
+ @attributes ||= {}
87
+ @attributes[name] = value
88
+ end
89
+
90
+ # Maps all attributes using the given block
91
+ #
92
+ # @example Stringify attributes
93
+ # person.attributes_map { |name| send(name).to_s }
94
+ #
95
+ # @yield [name] block called to return hash value
96
+ # @yieldparam [String] name The name of the attribute to map.
97
+ #
98
+ # @return [Hash{String => Object}] The Hash of mapped attributes
99
+ def attributes_map
100
+ Hash[self.class.attribute_names.map { |name| [name, yield(name)] }]
101
+ end
102
+
103
+ def attribute?(name)
104
+ Neo4j::Shared::TypeConverters::BooleanConverter.to_ruby(read_attribute(name))
105
+ end
106
+
107
+ module ClassMethods
108
+ # Defines an attribute
109
+ #
110
+ # For each attribute that is defined, a getter and setter will be
111
+ # added as an instance method to the model. An
112
+ # {AttributeDefinition} instance will be added to result of the
113
+ # attributes class method.
114
+ #
115
+ # @example Define an attribute.
116
+ # attribute :name
117
+ #
118
+ # @param (see AttributeDefinition#initialize)
119
+ #
120
+ # @raise [DangerousAttributeError] if the attribute name conflicts with
121
+ # existing methods
122
+ #
123
+ # @return [AttributeDefinition] Attribute's definition
124
+ def attribute(name)
125
+ fail Neo4j::DangerousAttributeError, %(an attribute method named "#{name}" would conflict with an existing method) if dangerous_attribute?(name)
126
+
127
+ attribute!(name)
128
+ end
129
+
130
+ # Returns an Array of attribute names as Strings
131
+ #
132
+ # @example Get attribute names
133
+ # Person.attribute_names
134
+ #
135
+ # @return [Array<String>] The attribute names
136
+ def attribute_names
137
+ attributes.keys
138
+ end
139
+
140
+ # Returns a Hash of AttributeDefinition instances
141
+ #
142
+ # @example Get attribute definitions
143
+ # Person.attributes
144
+ #
145
+ # @return [ActiveSupport::HashWithIndifferentAccess{String => Neo4j::Shared::AttributeDefinition}]
146
+ # The Hash of AttributeDefinition instances
147
+ def attributes
148
+ @attributes ||= ActiveSupport::HashWithIndifferentAccess.new
149
+ end
150
+
151
+ # Determine if a given attribute name is dangerous
152
+ #
153
+ # Some attribute names can cause conflicts with existing methods
154
+ # on an object. For example, an attribute named "timeout" would
155
+ # conflict with the timeout method that Ruby's Timeout library
156
+ # mixes into Object.
157
+ #
158
+ # @example Testing a harmless attribute
159
+ # Person.dangerous_attribute? :name #=> false
160
+ #
161
+ # @example Testing a dangerous attribute
162
+ # Person.dangerous_attribute? :nil #=> "nil?"
163
+ #
164
+ # @param name Attribute name
165
+ #
166
+ # @return [false, String] False or the conflicting method name
167
+ def dangerous_attribute?(name)
168
+ methods = instance_methods
169
+
170
+ attribute_methods(name).detect do |method_name|
171
+ !DEPRECATED_OBJECT_METHODS.include?(method_name.to_s) && methods.include?(method_name)
172
+ end unless attribute_names.include? name.to_s
173
+ end
174
+
175
+ # Returns the class name plus its attribute names
176
+ #
177
+ # @example Inspect the model's definition.
178
+ # Person.inspect
179
+ #
180
+ # @return [String] Human-readable presentation of the attributes
181
+ def inspect
182
+ inspected_attributes = attribute_names.sort
183
+ attributes_list = "(#{inspected_attributes.join(', ')})" unless inspected_attributes.empty?
184
+ "#{name}#{attributes_list}"
185
+ end
186
+
187
+ protected
188
+
189
+ # Assign a set of attribute definitions, used when subclassing models
190
+ #
191
+ # @param [Array<Neo4j::Shared::DeclaredProperties>] The Array of
192
+ # AttributeDefinition instances
193
+ def attributes=(attributes)
194
+ @attributes = attributes
195
+ end
196
+
197
+ # Overrides ActiveModel::AttributeMethods to backport 3.2 fix
198
+ def instance_method_already_implemented?(method_name)
199
+ generated_attribute_methods.method_defined?(method_name)
200
+ end
201
+
202
+ private
203
+
204
+ # Expand an attribute name into its generated methods names
205
+ def attribute_methods(name)
206
+ attribute_method_matchers.map { |matcher| matcher.method_name name }
207
+ end
208
+
209
+ # Ruby inherited hook to assign superclass attributes to subclasses
210
+ def inherited(subclass)
211
+ super
212
+ subclass.attributes = attributes.dup
213
+ end
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,68 @@
1
+ module Neo4j
2
+ module Shared
3
+ module Callbacks #:nodoc:
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ include ActiveModel::Callbacks
8
+ end
9
+
10
+ included do
11
+ include ActiveModel::Validations::Callbacks
12
+ # after_find is triggered by the `find` method defined in lib/neo4j/active_node/id_property.rb
13
+ define_model_callbacks :initialize, :find, only: :after
14
+ define_model_callbacks :create_commit, :update_commit, :destroy_commit, only: :after
15
+ define_model_callbacks :save, :create, :update, :destroy, :touch
16
+ end
17
+
18
+ def initialize(args = nil)
19
+ run_callbacks(:initialize) { super }
20
+ end
21
+
22
+ def destroy #:nodoc:
23
+ tx = Neo4j::ActiveBase.new_transaction
24
+ tx.root.after_commit { run_callbacks(:destroy_commit) {} }
25
+ run_callbacks(:destroy) { super }
26
+ rescue
27
+ @_deleted = false
28
+ @attributes = @attributes.dup
29
+ tx.mark_failed if tx
30
+ raise
31
+ ensure
32
+ tx.close if tx
33
+ end
34
+
35
+ def touch #:nodoc:
36
+ run_callbacks(:touch) { super }
37
+ end
38
+
39
+ # Allows you to perform a callback if a condition is not satisfied.
40
+ # @param [Symbol] kind The callback type to execute unless the guard is true
41
+ # @param [TrueClass,FalseClass] guard When this value is true, the block is yielded without executing callbacks.
42
+ def conditional_callback(kind, guard)
43
+ return yield if guard
44
+ run_callbacks(kind) { yield }
45
+ end
46
+
47
+ private
48
+
49
+ def create_or_update #:nodoc:
50
+ run_callbacks(:save) { super }
51
+ end
52
+
53
+ def create_model #:nodoc:
54
+ self.class.run_transaction do |tx|
55
+ tx.root.after_commit { run_callbacks(:create_commit) {} }
56
+ run_callbacks(:create) { super }
57
+ end
58
+ end
59
+
60
+ def update_model(*) #:nodoc:
61
+ self.class.run_transaction do |tx|
62
+ tx.root.after_commit { run_callbacks(:update_commit) {} }
63
+ run_callbacks(:update) { super }
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end