activegraph 10.0.0.pre.alpha.6

Sign up to get free protection for your applications and to get access to all the features.
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