neo4j 7.2.3 → 8.0.0.alpha.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -46
- data/Gemfile +15 -14
- data/README.md +21 -14
- data/bin/neo4j-jars +1 -1
- data/lib/neo4j.rb +12 -1
- data/lib/neo4j/active_base.rb +68 -0
- data/lib/neo4j/active_base/session_registry.rb +12 -0
- data/lib/neo4j/active_node.rb +13 -21
- data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +6 -6
- data/lib/neo4j/active_node/enum.rb +3 -6
- data/lib/neo4j/active_node/has_n.rb +24 -19
- data/lib/neo4j/active_node/has_n/association.rb +6 -2
- data/lib/neo4j/active_node/has_n/association/rel_factory.rb +1 -1
- data/lib/neo4j/active_node/has_n/association/rel_wrapper.rb +1 -1
- data/lib/neo4j/active_node/has_n/association_cypher_methods.rb +1 -1
- data/lib/neo4j/active_node/id_property.rb +52 -15
- data/lib/neo4j/active_node/labels.rb +32 -10
- data/lib/neo4j/active_node/labels/index.rb +5 -55
- data/lib/neo4j/active_node/node_list_formatter.rb +13 -0
- data/lib/neo4j/active_node/node_wrapper.rb +39 -37
- data/lib/neo4j/active_node/persistence.rb +27 -13
- data/lib/neo4j/active_node/query/query_proxy.rb +11 -9
- data/lib/neo4j/active_node/query/query_proxy_eager_loading.rb +4 -4
- data/lib/neo4j/active_node/query/query_proxy_enumerable.rb +1 -0
- data/lib/neo4j/active_node/query/query_proxy_link.rb +13 -9
- data/lib/neo4j/active_node/query/query_proxy_methods.rb +76 -8
- data/lib/neo4j/active_node/query/query_proxy_methods_of_mass_updating.rb +1 -1
- data/lib/neo4j/active_node/query_methods.rb +3 -3
- data/lib/neo4j/active_node/scope.rb +24 -7
- data/lib/neo4j/active_rel.rb +21 -3
- data/lib/neo4j/active_rel/initialize.rb +2 -2
- data/lib/neo4j/active_rel/persistence.rb +32 -6
- data/lib/neo4j/active_rel/persistence/query_factory.rb +3 -3
- data/lib/neo4j/active_rel/property.rb +9 -9
- data/lib/neo4j/active_rel/query.rb +6 -4
- data/lib/neo4j/active_rel/rel_wrapper.rb +24 -16
- data/lib/neo4j/active_rel/related_node.rb +5 -1
- data/lib/neo4j/active_rel/types.rb +2 -2
- data/lib/neo4j/config.rb +0 -1
- data/lib/neo4j/errors.rb +3 -0
- data/lib/neo4j/migration.rb +90 -71
- data/lib/neo4j/migrations.rb +10 -0
- data/lib/neo4j/migrations/base.rb +44 -0
- data/lib/neo4j/migrations/helpers.rb +101 -0
- data/lib/neo4j/migrations/helpers/id_property.rb +75 -0
- data/lib/neo4j/migrations/helpers/relationships.rb +66 -0
- data/lib/neo4j/migrations/helpers/schema.rb +53 -0
- data/lib/neo4j/migrations/migration_file.rb +24 -0
- data/lib/neo4j/migrations/runner.rb +110 -0
- data/lib/neo4j/migrations/schema_migration.rb +9 -0
- data/lib/neo4j/model_schema.rb +100 -0
- data/lib/neo4j/railtie.rb +29 -110
- data/lib/neo4j/schema/operation.rb +24 -13
- data/lib/neo4j/session_manager.rb +137 -0
- data/lib/neo4j/shared.rb +20 -11
- data/lib/neo4j/shared/attributes.rb +10 -16
- data/lib/neo4j/shared/callbacks.rb +3 -3
- data/lib/neo4j/shared/cypher.rb +1 -1
- data/lib/neo4j/shared/declared_properties.rb +1 -1
- data/lib/neo4j/shared/declared_property.rb +1 -1
- data/lib/neo4j/shared/enum.rb +6 -18
- data/lib/neo4j/shared/identity.rb +27 -21
- data/lib/neo4j/shared/persistence.rb +26 -17
- data/lib/neo4j/shared/property.rb +5 -2
- data/lib/neo4j/shared/query_factory.rb +4 -5
- data/lib/neo4j/shared/type_converters.rb +8 -9
- data/lib/neo4j/shared/validations.rb +1 -5
- data/lib/neo4j/tasks/migration.rake +83 -2
- data/lib/neo4j/version.rb +1 -1
- data/lib/rails/generators/neo4j/migration/migration_generator.rb +14 -0
- data/lib/rails/generators/neo4j/migration/templates/migration.erb +9 -0
- data/lib/rails/generators/neo4j/model/model_generator.rb +1 -3
- data/lib/rails/generators/neo4j_generator.rb +1 -0
- data/neo4j.gemspec +3 -3
- metadata +58 -65
- data/bin/rake +0 -17
- data/lib/neo4j/shared/permitted_attributes.rb +0 -28
@@ -6,12 +6,9 @@ module Neo4j::ActiveNode
|
|
6
6
|
module ClassMethods
|
7
7
|
protected
|
8
8
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
else
|
13
|
-
super
|
14
|
-
end
|
9
|
+
def define_property(property_name, *args)
|
10
|
+
super
|
11
|
+
Neo4j::ModelSchema.add_required_index(self, property_name)
|
15
12
|
end
|
16
13
|
|
17
14
|
def define_enum_methods(property_name, enum_keys, options)
|
@@ -23,11 +23,8 @@ module Neo4j::ActiveNode
|
|
23
23
|
# States:
|
24
24
|
# Default
|
25
25
|
def inspect
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
"#<AssociationProxy @query_proxy=#{@query_proxy.inspect}>"
|
30
|
-
end
|
26
|
+
formatted_nodes = ::Neo4j::ActiveNode::NodeListFormatter.new(result_nodes)
|
27
|
+
"#<AssociationProxy #{@query_proxy.context} #{formatted_nodes.inspect}>"
|
31
28
|
end
|
32
29
|
|
33
30
|
extend Forwardable
|
@@ -212,7 +209,9 @@ module Neo4j::ActiveNode
|
|
212
209
|
end
|
213
210
|
end
|
214
211
|
|
212
|
+
# rubocop:disable Metrics/ModuleLength
|
215
213
|
module ClassMethods
|
214
|
+
# rubocop:enable Style/PredicateName
|
216
215
|
# rubocop:disable Style/PredicateName
|
217
216
|
|
218
217
|
# :nocov:
|
@@ -229,21 +228,18 @@ module Neo4j::ActiveNode
|
|
229
228
|
!!associations[name.to_sym]
|
230
229
|
end
|
231
230
|
|
231
|
+
def parent_associations
|
232
|
+
superclass == Object ? {} : superclass.associations
|
233
|
+
end
|
234
|
+
|
232
235
|
def associations
|
233
|
-
@associations ||=
|
236
|
+
(@associations ||= parent_associations.dup)
|
234
237
|
end
|
235
238
|
|
236
239
|
def associations_keys
|
237
240
|
@associations_keys ||= associations.keys
|
238
241
|
end
|
239
242
|
|
240
|
-
# make sure the inherited classes inherit the <tt>_decl_rels</tt> hash
|
241
|
-
def inherited(klass)
|
242
|
-
klass.instance_variable_set(:@associations, associations.clone)
|
243
|
-
@associations_keys = klass.associations_keys.clone
|
244
|
-
super
|
245
|
-
end
|
246
|
-
|
247
243
|
# For defining an "has many" association on a model. This defines a set of methods on
|
248
244
|
# your model instances. For instance, if you define the association on a Person model:
|
249
245
|
#
|
@@ -379,7 +375,7 @@ module Neo4j::ActiveNode
|
|
379
375
|
|
380
376
|
clear_deferred_nodes_for_association(name)
|
381
377
|
|
382
|
-
|
378
|
+
self.class.run_transaction { association_proxy(name).replace_with(other_nodes) }
|
383
379
|
end
|
384
380
|
end
|
385
381
|
|
@@ -455,7 +451,7 @@ module Neo4j::ActiveNode
|
|
455
451
|
if persisted?
|
456
452
|
other_node.save if other_node.respond_to?(:persisted?) && !other_node.persisted?
|
457
453
|
association_proxy_cache.clear # TODO: Should probably just clear for this association...
|
458
|
-
|
454
|
+
self.class.run_transaction { association_proxy(name).replace_with(other_node) }
|
459
455
|
# handle_non_persisted_node(other_node)
|
460
456
|
else
|
461
457
|
defer_create(name, other_node, clear: true)
|
@@ -509,24 +505,33 @@ module Neo4j::ActiveNode
|
|
509
505
|
|
510
506
|
def default_association_query_proxy
|
511
507
|
Neo4j::ActiveNode::Query::QueryProxy.new("::#{self.name}".constantize, nil,
|
512
|
-
session: neo4j_session, query_proxy: nil, context:
|
508
|
+
session: neo4j_session, query_proxy: nil, context: self.name.to_s)
|
513
509
|
end
|
514
510
|
|
515
511
|
def build_association(macro, direction, name, options)
|
516
512
|
options[:model_class] = options[:model_class].name if options[:model_class] == self
|
517
513
|
Neo4j::ActiveNode::HasN::Association.new(macro, direction, name, options).tap do |association|
|
518
|
-
|
519
|
-
@associations[name] = association
|
514
|
+
add_association(name, association)
|
520
515
|
create_reflection(macro, name, association, self)
|
521
516
|
end
|
522
517
|
|
523
|
-
associations_keys
|
518
|
+
@associations_keys = nil
|
524
519
|
|
525
520
|
# Re-raise any exception with added class name and association name to
|
526
521
|
# make sure error message is helpful
|
527
522
|
rescue StandardError => e
|
528
523
|
raise e.class, "#{e.message} (#{self.class}##{name})"
|
529
524
|
end
|
525
|
+
|
526
|
+
def add_association(name, association_object)
|
527
|
+
fail "Association `#{name}` defined for a second time. "\
|
528
|
+
'Associations can only be defined once' if duplicate_association?(name)
|
529
|
+
associations[name] = association_object
|
530
|
+
end
|
531
|
+
|
532
|
+
def duplicate_association?(name)
|
533
|
+
associations.key?(name) && parent_associations[name] != associations[name]
|
534
|
+
end
|
530
535
|
end
|
531
536
|
end
|
532
537
|
end
|
@@ -67,6 +67,10 @@ module Neo4j
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
def inverse_of?(other)
|
71
|
+
origin_association == other
|
72
|
+
end
|
73
|
+
|
70
74
|
def target_classes
|
71
75
|
ClassArguments.constantize_argument(target_class_names)
|
72
76
|
end
|
@@ -151,7 +155,7 @@ module Neo4j
|
|
151
155
|
def relationship_class?
|
152
156
|
!!relationship_class
|
153
157
|
end
|
154
|
-
|
158
|
+
alias rel_class? relationship_class?
|
155
159
|
|
156
160
|
private
|
157
161
|
|
@@ -216,7 +220,7 @@ module Neo4j
|
|
216
220
|
message = case
|
217
221
|
when (message = type_keys_error_message(options.keys))
|
218
222
|
message
|
219
|
-
when (unknown_keys = options.keys - VALID_ASSOCIATION_OPTION_KEYS).
|
223
|
+
when !(unknown_keys = options.keys - VALID_ASSOCIATION_OPTION_KEYS).empty?
|
220
224
|
"Unknown option(s) specified: #{unknown_keys.join(', ')}"
|
221
225
|
end
|
222
226
|
|
@@ -44,7 +44,7 @@ module Neo4j::ActiveNode::HasN
|
|
44
44
|
|
45
45
|
def _match_query(other_node, wrapper)
|
46
46
|
nodes = _nodes_for_create(other_node, wrapper.from_node_identifier, wrapper.to_node_identifier)
|
47
|
-
Neo4j::
|
47
|
+
Neo4j::ActiveBase.new_query.match_nodes(nodes)
|
48
48
|
end
|
49
49
|
|
50
50
|
def _nodes_for_create(other_node, from_node_id, to_node_id)
|
@@ -7,7 +7,7 @@ class Neo4j::ActiveNode::HasN::Association
|
|
7
7
|
attr_reader :type, :association
|
8
8
|
attr_accessor :properties
|
9
9
|
private :association
|
10
|
-
|
10
|
+
alias props_for_create properties
|
11
11
|
|
12
12
|
def initialize(association, properties = {})
|
13
13
|
@association = association
|
@@ -40,6 +40,8 @@ module Neo4j::ActiveNode
|
|
40
40
|
def define_id_methods(clazz, name, conf)
|
41
41
|
validate_conf!(conf)
|
42
42
|
|
43
|
+
return if name == :neo_id
|
44
|
+
|
43
45
|
if conf[:on]
|
44
46
|
define_custom_method(clazz, name, conf[:on])
|
45
47
|
elsif conf[:auto]
|
@@ -125,7 +127,7 @@ module Neo4j::ActiveNode
|
|
125
127
|
attr_accessor :manual_id_property
|
126
128
|
|
127
129
|
def find_by_neo_id(id)
|
128
|
-
|
130
|
+
find_by(neo_id: id)
|
129
131
|
end
|
130
132
|
|
131
133
|
def find_by_id(id)
|
@@ -136,13 +138,11 @@ module Neo4j::ActiveNode
|
|
136
138
|
all.where(id_property_name => ids).to_a
|
137
139
|
end
|
138
140
|
|
139
|
-
def id_property(name, conf = {})
|
141
|
+
def id_property(name, conf = {}, inherited = false)
|
140
142
|
self.manual_id_property = true
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
constraint(name, type: :unique) unless conf[:constraint] == false
|
145
|
-
end
|
143
|
+
|
144
|
+
@id_property_info = {name: name, type: conf, inherited: inherited}
|
145
|
+
TypeMethods.define_id_methods(self, name, conf)
|
146
146
|
end
|
147
147
|
|
148
148
|
# rubocop:disable Style/PredicateName
|
@@ -158,6 +158,8 @@ module Neo4j::ActiveNode
|
|
158
158
|
end
|
159
159
|
|
160
160
|
def id_property_info
|
161
|
+
ensure_id_property_info!
|
162
|
+
|
161
163
|
@id_property_info ||= {}
|
162
164
|
end
|
163
165
|
|
@@ -169,18 +171,53 @@ module Neo4j::ActiveNode
|
|
169
171
|
!!manual_id_property
|
170
172
|
end
|
171
173
|
|
172
|
-
|
174
|
+
alias primary_key id_property_name
|
175
|
+
|
176
|
+
# Since there's no way to know when a class is done being described, we wait until the id_property
|
177
|
+
# information is requested and use that as the opportunity to set up the defaults if no others are specified
|
178
|
+
def ensure_id_property_info!
|
179
|
+
if !manual_id_property? && !@id_property_info
|
180
|
+
name, type, value = id_property_name_type_value
|
181
|
+
id_property(name, type => value)
|
182
|
+
end
|
183
|
+
|
184
|
+
handle_model_schema!
|
185
|
+
end
|
173
186
|
|
174
187
|
private
|
175
188
|
|
176
|
-
def
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
189
|
+
def handle_model_schema!
|
190
|
+
id_property_name = @id_property_info[:name]
|
191
|
+
if @id_property_info[:type][:constraint] == false &&
|
192
|
+
!@id_property_info[:inherited] &&
|
193
|
+
!@id_property_info[:warned_of_constraint]
|
194
|
+
@id_property_info[:warned_of_constraint] = true
|
195
|
+
warn_constraint_option_false!(id_property_name)
|
196
|
+
return
|
182
197
|
end
|
183
|
-
|
198
|
+
|
199
|
+
return if id_property_name == :neo_id || @id_property_info[:inherited]
|
200
|
+
|
201
|
+
Neo4j::ModelSchema.add_defined_constraint(self, id_property_name)
|
202
|
+
end
|
203
|
+
|
204
|
+
def warn_constraint_option_false!(id_property_name)
|
205
|
+
Neo4j::ActiveBase.logger.warn <<MSG
|
206
|
+
WARNING: The constraint option for id_property is no longer supported (Used on #{self.name}.#{id_property_name}).
|
207
|
+
Since you specified `constraint: false` this option can simply be removed.
|
208
|
+
MSG
|
209
|
+
end
|
210
|
+
|
211
|
+
def id_property_name_type_value
|
212
|
+
name, type, value = Neo4j::Config.to_hash.values_at(*%w(id_property id_property_type id_property_type_value))
|
213
|
+
|
214
|
+
if !(name && type && value)
|
215
|
+
name = :uuid
|
216
|
+
type = :auto
|
217
|
+
value = :uuid
|
218
|
+
end
|
219
|
+
|
220
|
+
[name, type, value]
|
184
221
|
end
|
185
222
|
end
|
186
223
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'neo4j/core/label'
|
2
|
+
|
1
3
|
module Neo4j
|
2
4
|
module ActiveNode
|
3
5
|
# Provides a mapping between neo4j labels and Ruby classes
|
@@ -11,7 +13,11 @@ module Neo4j
|
|
11
13
|
MODELS_FOR_LABELS_CACHE.clear
|
12
14
|
|
13
15
|
included do |model|
|
14
|
-
|
16
|
+
def self.inherited(model)
|
17
|
+
add_wrapped_class(model)
|
18
|
+
|
19
|
+
super
|
20
|
+
end
|
15
21
|
|
16
22
|
Neo4j::ActiveNode::Labels.add_wrapped_class(model) unless Neo4j::ActiveNode::Labels._wrapped_classes.include?(model)
|
17
23
|
end
|
@@ -31,15 +37,32 @@ module Neo4j
|
|
31
37
|
|
32
38
|
# adds one or more labels
|
33
39
|
# @see Neo4j-core
|
34
|
-
def
|
35
|
-
|
40
|
+
def add_labels(*labels)
|
41
|
+
labels.inject(query_as(:n)) do |query, label|
|
42
|
+
query.set("n:`#{label}`")
|
43
|
+
end.exec
|
44
|
+
@_persisted_obj.labels.concat(labels)
|
45
|
+
@_persisted_obj.labels.uniq!
|
46
|
+
end
|
47
|
+
|
48
|
+
# Remove this method in 9.0.0
|
49
|
+
def add_label(*_labels)
|
50
|
+
fail 'add_label has been removed in favor of `add_labels`'
|
36
51
|
end
|
37
52
|
|
38
53
|
# Removes one or more labels
|
39
54
|
# Be careful, don't remove the label representing the Ruby class.
|
40
55
|
# @see Neo4j-core
|
41
|
-
def
|
42
|
-
|
56
|
+
def remove_labels(*labels)
|
57
|
+
labels.inject(query_as(:n)) do |query, label|
|
58
|
+
query.remove("n:`#{label}`")
|
59
|
+
end.exec
|
60
|
+
labels.each(&@_persisted_obj.labels.method(:delete))
|
61
|
+
end
|
62
|
+
|
63
|
+
# Remove this method in 9.0.0
|
64
|
+
def remove_label(*_labels)
|
65
|
+
fail 'remove_label has been removed in favor of `remove_labels`'
|
43
66
|
end
|
44
67
|
|
45
68
|
def self._wrapped_classes
|
@@ -56,7 +79,7 @@ module Neo4j
|
|
56
79
|
return MODELS_FOR_LABELS_CACHE[labels] if MODELS_FOR_LABELS_CACHE[labels]
|
57
80
|
|
58
81
|
models = WRAPPED_CLASSES.select do |model|
|
59
|
-
(model.mapped_label_names - labels).
|
82
|
+
(model.mapped_label_names - labels).empty?
|
60
83
|
end
|
61
84
|
|
62
85
|
MODELS_FOR_LABELS_CACHE[labels] = models.max_by do |model|
|
@@ -66,7 +89,7 @@ module Neo4j
|
|
66
89
|
|
67
90
|
def self.clear_wrapped_models
|
68
91
|
MODELS_FOR_LABELS_CACHE.clear
|
69
|
-
Neo4j::
|
92
|
+
Neo4j::NodeWrapping::CONSTANTS_FOR_LABELS_CACHE.clear
|
70
93
|
end
|
71
94
|
|
72
95
|
module ClassMethods
|
@@ -100,8 +123,7 @@ module Neo4j
|
|
100
123
|
|
101
124
|
# Deletes all nodes and connected relationships from Cypher.
|
102
125
|
def delete_all
|
103
|
-
|
104
|
-
self.neo4j_session._query("MATCH (n:`#{mapped_label_name}`) DELETE n")
|
126
|
+
neo4j_query("MATCH (n:`#{mapped_label_name}`) OPTIONAL MATCH (n)-[r]-() DELETE n,r")
|
105
127
|
end
|
106
128
|
|
107
129
|
# Returns each node to Ruby and calls `destroy`. Be careful, as this can be a very slow operation if you have many nodes. It will generate at least
|
@@ -122,7 +144,7 @@ module Neo4j
|
|
122
144
|
|
123
145
|
# @return [Neo4j::Label] the label for this class
|
124
146
|
def mapped_label
|
125
|
-
Neo4j::Label.
|
147
|
+
Neo4j::Core::Label.new(mapped_label_name, neo4j_session)
|
126
148
|
end
|
127
149
|
|
128
150
|
def base_class
|
@@ -20,67 +20,17 @@ module Neo4j::ActiveNode::Labels
|
|
20
20
|
# index :name
|
21
21
|
# end
|
22
22
|
def index(property)
|
23
|
-
Neo4j::
|
24
|
-
|
25
|
-
|
26
|
-
end
|
23
|
+
return if Neo4j::ModelSchema.defined_constraint?(self, property)
|
24
|
+
|
25
|
+
Neo4j::ModelSchema.add_defined_index(self, property)
|
27
26
|
end
|
28
27
|
|
29
28
|
# Creates a neo4j constraint on this class for given property
|
30
29
|
#
|
31
30
|
# @example
|
32
31
|
# Person.constraint :name, type: :unique
|
33
|
-
def constraint(property,
|
34
|
-
Neo4j::
|
35
|
-
declared_properties.constraint_or_fail!(property, id_property_name)
|
36
|
-
schema_create_operation(:constraint, property, constraints)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# @param [Symbol] property The name of the property index to be dropped
|
41
|
-
def drop_index(property, options = {})
|
42
|
-
Neo4j::Session.on_next_session_available do
|
43
|
-
declared_properties[property].unindex! if declared_properties[property]
|
44
|
-
schema_drop_operation(:index, property, options)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# @param [Symbol] property The name of the property constraint to be dropped
|
49
|
-
# @param [Hash] constraint The constraint type to be dropped.
|
50
|
-
def drop_constraint(property, constraint = {type: :unique})
|
51
|
-
Neo4j::Session.on_next_session_available do
|
52
|
-
declared_properties[property].unconstraint! if declared_properties[property]
|
53
|
-
schema_drop_operation(:constraint, property, constraint)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def index?(property)
|
58
|
-
mapped_label.indexes[:property_keys].include?([property])
|
59
|
-
end
|
60
|
-
|
61
|
-
def constraint?(property)
|
62
|
-
mapped_label.unique_constraints[:property_keys].include?([property])
|
63
|
-
end
|
64
|
-
|
65
|
-
private
|
66
|
-
|
67
|
-
def schema_create_operation(type, property, options = {})
|
68
|
-
new_schema_class(type, property, options).create!
|
69
|
-
end
|
70
|
-
|
71
|
-
def schema_drop_operation(type, property, options = {})
|
72
|
-
new_schema_class(type, property, options).drop!
|
73
|
-
end
|
74
|
-
|
75
|
-
def new_schema_class(type, property, options)
|
76
|
-
case type
|
77
|
-
when :index
|
78
|
-
Neo4j::Schema::ExactIndexOperation
|
79
|
-
when :constraint
|
80
|
-
Neo4j::Schema::UniqueConstraintOperation
|
81
|
-
else
|
82
|
-
fail "Unknown Schema Operation class #{type}"
|
83
|
-
end.new(mapped_label_name, property, options)
|
32
|
+
def constraint(property, _constraints = {type: :unique})
|
33
|
+
Neo4j::ModelSchema.add_defined_constraint(self, property)
|
84
34
|
end
|
85
35
|
end
|
86
36
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Neo4j::ActiveNode
|
2
|
+
class NodeListFormatter
|
3
|
+
def initialize(list, max_elements = 5)
|
4
|
+
@list = list
|
5
|
+
@max_elements = max_elements
|
6
|
+
end
|
7
|
+
|
8
|
+
def inspect
|
9
|
+
return @list.inspect if !@max_elements || @list.length <= @max_elements
|
10
|
+
"[#{@list.take(5).map!(&:inspect).join(', ')}, ...]"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|