neo4j 7.2.3 → 8.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|