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,224 @@
1
+ module ActiveGraph::Node
2
+ # This module makes it possible to use other IDs than the build it neo4j id (neo_id)
3
+ #
4
+ # @example using generated UUIDs
5
+ # class Person
6
+ # include ActiveGraph::Node
7
+ # # creates a 'secret' neo4j property my_uuid which will be used as primary key
8
+ # id_property :my_uuid, auto: :uuid
9
+ # end
10
+ #
11
+ # @example using user defined ids
12
+ # class Person
13
+ # include ActiveGraph::Node
14
+ # property :title
15
+ # validates :title, :presence => true
16
+ # id_property :title_id, on: :title_to_url
17
+ #
18
+ # def title_to_url
19
+ # self.title.urlize # uses https://github.com/cheef/string-urlize gem
20
+ # end
21
+ # end
22
+ #
23
+ # @example using already exsting ids that you don't want a constraint added to
24
+ # class Person
25
+ # include ActiveGraph::Node
26
+ # property :title
27
+ # validates :title, :presence => true
28
+ # id_property :id, on: :id_builder, constraint: false
29
+ #
30
+ # def id_builder
31
+ # # only need to fill this out if you're gonna write to the db
32
+ # end
33
+ # end
34
+ #
35
+ module IdProperty
36
+ extend ActiveSupport::Concern
37
+ include Accessor
38
+
39
+ module TypeMethods
40
+ def define_id_methods(clazz, name, conf)
41
+ return if name == :neo_id
42
+
43
+ validate_conf!(conf)
44
+
45
+ if conf[:on]
46
+ define_custom_method(clazz, name, conf[:on])
47
+ elsif conf[:auto]
48
+ define_uuid_method(clazz, name)
49
+ elsif conf.empty?
50
+ define_property_method(clazz, name)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def validate_conf!(conf)
57
+ fail "Expected a Hash, got #{conf.class} (#{conf}) for id_property" if !conf.is_a?(Hash)
58
+
59
+ return if conf[:on]
60
+
61
+ if conf[:auto]
62
+ fail "only :uuid auto id_property allowed, got #{conf[:auto]}" if conf[:auto] != :uuid
63
+ return
64
+ end
65
+
66
+ return if conf.empty?
67
+
68
+ fail "Illegal value #{conf.inspect} for id_property, expected :on or :auto"
69
+ end
70
+
71
+ def define_property_method(clazz, name)
72
+ clear_methods(clazz, name)
73
+
74
+ clazz.module_eval(%(
75
+ def id
76
+ _persisted_obj ? #{name.to_sym == :id ? 'attribute(\'id\')' : name} : nil
77
+ end
78
+
79
+ property :#{name}
80
+ ), __FILE__, __LINE__)
81
+ end
82
+
83
+
84
+ def define_uuid_method(clazz, name)
85
+ clear_methods(clazz, name)
86
+
87
+ clazz.module_eval(%(
88
+ default_property :#{name} do
89
+ ::SecureRandom.uuid
90
+ end
91
+
92
+ def #{name}
93
+ default_property_value
94
+ end
95
+
96
+ alias_method :id, :#{name}
97
+ ), __FILE__, __LINE__)
98
+ end
99
+
100
+ def define_custom_method(clazz, name, on)
101
+ clear_methods(clazz, name)
102
+
103
+ clazz.module_eval(%{
104
+ default_property :#{name} do |instance|
105
+ raise "Specifying custom id_property #{name} on non-existent method #{on}" unless instance.respond_to?(:#{on})
106
+ instance.#{on}
107
+ end
108
+
109
+ def #{name}
110
+ default_property_value
111
+ end
112
+
113
+ alias_method :id, :#{name}
114
+ }, __FILE__, __LINE__)
115
+ end
116
+
117
+ def clear_methods(clazz, name)
118
+ clazz.module_eval(%(undef_method :#{name}), __FILE__, __LINE__) if clazz.method_defined?(name)
119
+ clazz.module_eval(%(undef_property :#{name}), __FILE__, __LINE__) if clazz.attribute_names.include?(name.to_s)
120
+ end
121
+
122
+ extend self
123
+ end
124
+
125
+
126
+ module ClassMethods
127
+ attr_accessor :manual_id_property
128
+
129
+ def find_by_neo_id(id)
130
+ find_by(neo_id: id)
131
+ end
132
+
133
+ def find_by_id(id)
134
+ all.where(id_property_name => id).first
135
+ end
136
+
137
+ def find_by_ids(ids)
138
+ all.where(id_property_name => ids).to_a
139
+ end
140
+
141
+ def id_property(name, conf = {}, inherited = false)
142
+ self.manual_id_property = true
143
+
144
+ @id_property_info = {name: name, type: conf, inherited: inherited}
145
+ TypeMethods.define_id_methods(self, name, conf)
146
+ end
147
+
148
+ # rubocop:disable Naming/PredicateName
149
+ def has_id_property?
150
+ ActiveSupport::Deprecation.warn 'has_id_property? is deprecated and may be removed from future releases, use id_property? instead.', caller
151
+
152
+ id_property?
153
+ end
154
+ # rubocop:enable Naming/PredicateName
155
+
156
+ def id_property?
157
+ id_property_info && !id_property_info.empty?
158
+ end
159
+
160
+ def id_property_info
161
+ ensure_id_property_info!
162
+
163
+ @id_property_info ||= {}
164
+ end
165
+
166
+ def id_property_name
167
+ id_property_info[:name]
168
+ end
169
+
170
+ def manual_id_property?
171
+ !!manual_id_property
172
+ end
173
+
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
186
+
187
+ private
188
+
189
+ def handle_model_schema!
190
+ id_property_name = @id_property_info[:name]
191
+
192
+ return if id_property_name == :neo_id || @id_property_info[:inherited]
193
+
194
+ if @id_property_info[:type][:constraint] == false &&
195
+ !@id_property_info[:warned_of_constraint]
196
+ @id_property_info[:warned_of_constraint] = true
197
+ warn_constraint_option_false!(id_property_name)
198
+ return
199
+ end
200
+
201
+ ActiveGraph::ModelSchema.add_defined_constraint(self, id_property_name)
202
+ end
203
+
204
+ def warn_constraint_option_false!(id_property_name)
205
+ ActiveGraph::Base.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 = ActiveGraph::Config.to_hash.values_at('id_property', 'id_property_type', 'id_property_type_value')
213
+
214
+ unless name == :neo_id || (name && type && value)
215
+ name = :uuid
216
+ type = :auto
217
+ value = :uuid
218
+ end
219
+
220
+ [name, type, value]
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,62 @@
1
+ module ActiveGraph::Node::IdProperty
2
+ # Provides get/set of the Id Property values.
3
+ # Some methods
4
+ module Accessor
5
+ extend ActiveSupport::Concern
6
+
7
+ attr_reader :default_property_value
8
+
9
+ def default_properties=(properties)
10
+ @default_property_value = properties[default_property_key]
11
+ end
12
+
13
+ def default_property(key)
14
+ return nil unless key == default_property_key
15
+ default_property_value
16
+ end
17
+
18
+ def default_property_key
19
+ self.class.default_property_key
20
+ end
21
+
22
+ def default_properties
23
+ @default_properties ||= Hash.new(nil)
24
+ end
25
+
26
+ module ClassMethods
27
+ def default_property_key
28
+ @default_property_key ||= default_properties_keys.first
29
+ end
30
+
31
+ # TODO: Move this to the DeclaredProperties
32
+ def default_property(name, &block)
33
+ reset_default_properties(name) if default_properties.respond_to?(:size)
34
+ default_properties[name] = block
35
+ end
36
+
37
+ # @return [Hash<Symbol,Proc>]
38
+ def default_properties
39
+ @default_property ||= {}
40
+ end
41
+
42
+ def default_properties_keys
43
+ @default_properties_keys ||= default_properties.keys
44
+ end
45
+
46
+ def reset_default_properties(name_to_keep)
47
+ default_properties.each_key do |property|
48
+ @default_properties_keys = nil
49
+ undef_method(property) unless property == name_to_keep
50
+ end
51
+ @default_properties_keys = nil
52
+ @default_property = {}
53
+ end
54
+
55
+ def default_property_values(instance)
56
+ default_properties.each_with_object({}) do |(key, block), result|
57
+ result[key] = block.call(instance)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveGraph::Node::Initialize
2
+ extend ActiveSupport::Concern
3
+ include ActiveGraph::Shared::Initialize
4
+
5
+ attr_reader :called_by
6
+
7
+ # called when loading the node from the database
8
+ # @param [ActiveGraph::Node] persisted_node the node this class wraps
9
+ # @param [Hash] properties of the persisted node.
10
+ def init_on_load(persisted_node, properties)
11
+ self.class.extract_association_attributes!(properties)
12
+ @_persisted_obj = persisted_node
13
+ changed_attributes_clear!
14
+ @attributes = convert_and_assign_attributes(properties)
15
+ end
16
+
17
+ def init_on_reload(reloaded)
18
+ @attributes = nil
19
+ init_on_load(reloaded, reloaded.properties)
20
+ end
21
+ end
@@ -0,0 +1,207 @@
1
+ require 'active_graph/core/label'
2
+
3
+ module ActiveGraph
4
+ module Node
5
+ # Provides a mapping between neo4j labels and Ruby classes
6
+ module Labels
7
+ extend ActiveSupport::Concern
8
+ include ActiveGraph::Node::Labels::Index
9
+ include ActiveGraph::Node::Labels::Reloading
10
+
11
+ WRAPPED_CLASSES = []
12
+ MODELS_FOR_LABELS_CACHE = {}
13
+ MODELS_FOR_LABELS_CACHE.clear
14
+
15
+ included do |model|
16
+ ActiveGraph::Node::Labels.clear_wrapped_models
17
+
18
+ ActiveGraph::Node::Labels.add_wrapped_class(model) unless ActiveGraph::Node::Labels._wrapped_classes.include?(model)
19
+ end
20
+
21
+ class RecordNotFound < ActiveGraph::RecordNotFound; end
22
+
23
+ # @return the labels
24
+ # @see ActiveGraph::Core
25
+ def labels
26
+ @_persisted_obj.labels
27
+ end
28
+
29
+ # this is handled by core, leaving it now for posterity
30
+ # def queried_labels
31
+ # self.class.query_as(:result).where("ID(result)" => self.neo_id).return("LABELS(result) as result_labels").first.result_labels.map(&:to_sym)
32
+ # end
33
+
34
+ # adds one or more labels
35
+ # @see ActiveGraph::Core
36
+ def add_labels(*labels)
37
+ labels.inject(query_as(:n)) do |query, label|
38
+ query.set("n:`#{label}`")
39
+ end.exec
40
+ @_persisted_obj.labels.concat(labels)
41
+ @_persisted_obj.labels.uniq!
42
+ end
43
+
44
+ # Removes one or more labels
45
+ # Be careful, don't remove the label representing the Ruby class.
46
+ # @see ActiveGraph::Core
47
+ def remove_labels(*labels)
48
+ labels.inject(query_as(:n)) do |query, label|
49
+ query.remove("n:`#{label}`")
50
+ end.exec
51
+ labels.each(&@_persisted_obj.labels.method(:delete))
52
+ end
53
+
54
+ def self._wrapped_classes
55
+ WRAPPED_CLASSES
56
+ end
57
+
58
+ def self.add_wrapped_class(model)
59
+ _wrapped_classes << model
60
+ end
61
+
62
+ # Finds an appropriate matching model given a set of labels
63
+ # which are assigned to a node
64
+ def self.model_for_labels(labels)
65
+ labels.sort!
66
+ return MODELS_FOR_LABELS_CACHE[labels] if MODELS_FOR_LABELS_CACHE[labels]
67
+
68
+ models = WRAPPED_CLASSES.select do |model|
69
+ (model.mapped_label_names - labels).empty?
70
+ end
71
+
72
+ MODELS_FOR_LABELS_CACHE[labels] = models.max_by do |model|
73
+ (model.mapped_label_names & labels).size
74
+ end
75
+ end
76
+
77
+ def self.clear_wrapped_models
78
+ MODELS_FOR_LABELS_CACHE.clear
79
+ ActiveGraph::NodeWrapping::CONSTANTS_FOR_LABELS_CACHE.clear
80
+ end
81
+
82
+ module ClassMethods
83
+ include ActiveGraph::Node::QueryMethods
84
+
85
+ delegate :update_all, to: :all
86
+
87
+ # Returns the object with the specified neo4j id.
88
+ # @param [String,Integer] id of node to find
89
+ def find(id)
90
+ map_id = proc { |object| object.respond_to?(:id) ? object.send(:id) : object }
91
+
92
+ result = find_by_id_or_ids(map_id, id)
93
+
94
+ fail RecordNotFound.new(
95
+ "Couldn't find #{name} with '#{id_property_name}'=#{id.inspect}",
96
+ name, id_property_name, id) if result.blank?
97
+ result.tap { |r| find_callbacks!(r) }
98
+ end
99
+
100
+ # Finds the first record matching the specified conditions. There is no implied ordering so if order matters, you should specify it yourself.
101
+ # @param values Hash args of arguments to find
102
+ def find_by(values)
103
+ all.where(values).limit(1).query_as(:n).pluck(:n).first
104
+ end
105
+
106
+ # Like find_by, except that if no record is found, raises a RecordNotFound error.
107
+ def find_by!(values)
108
+ find_by(values) || fail(RecordNotFound.new("#{self.query_as(:n).where(n: values).limit(1).to_cypher} returned no results", name))
109
+ end
110
+
111
+ # Deletes all nodes and connected relationships from Cypher.
112
+ def delete_all
113
+ neo4j_query("MATCH (n:`#{mapped_label_name}`) OPTIONAL MATCH (n)-[r]-() DELETE n,r")
114
+ end
115
+
116
+ # 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
117
+ # one database query per node in the database, more if callbacks require them.
118
+ def destroy_all
119
+ all.each(&:destroy)
120
+ end
121
+
122
+ # @return [Array{Symbol}] all the labels that this class has
123
+ def mapped_label_names
124
+ self.ancestors.find_all { |a| a.respond_to?(:mapped_label_name) }.map { |a| a.mapped_label_name.to_sym }
125
+ end
126
+
127
+ # @return [Symbol] the label that this class has which corresponds to a Ruby class
128
+ def mapped_label_name
129
+ @mapped_label_name || label_for_model
130
+ end
131
+
132
+ # @return [ActiveGraph::Label] the label for this class
133
+ def mapped_label
134
+ ActiveGraph::Core::Label.new(mapped_label_name)
135
+ end
136
+
137
+ def base_class
138
+ unless self < ActiveGraph::Node
139
+ fail "#{name} doesn't belong in a hierarchy descending from Node"
140
+ end
141
+
142
+ if superclass == Object
143
+ self
144
+ else
145
+ superclass.base_class
146
+ end
147
+ end
148
+
149
+ protected
150
+
151
+ def mapped_labels
152
+ mapped_label_names.map { |label_name| ActiveGraph::Label.create(label_name) }
153
+ end
154
+
155
+ def mapped_label_name=(name)
156
+ @mapped_label_name = name.to_sym
157
+ end
158
+
159
+ # rubocop:disable Naming/AccessorMethodName
160
+ def set_mapped_label_name(name)
161
+ ActiveSupport::Deprecation.warn 'set_mapped_label_name is deprecated, use self.mapped_label_name= instead.', caller
162
+
163
+ self.mapped_label_name = name
164
+ end
165
+ # rubocop:enable Naming/AccessorMethodName
166
+
167
+ private
168
+
169
+ def find_by_id_or_ids(map_id, id)
170
+ if id.is_a?(Array)
171
+ find_by_ids(id.map(&map_id))
172
+ else
173
+ find_by_id(map_id.call(id))
174
+ end
175
+ end
176
+
177
+ def find_callbacks!(result)
178
+ case result
179
+ when ActiveGraph::Node
180
+ result.run_callbacks(:find)
181
+ when Array
182
+ result.each { |r| find_callbacks!(r) }
183
+ else
184
+ result
185
+ end
186
+ end
187
+
188
+ def label_for_model
189
+ (self.name.nil? ? object_id.to_s.to_sym : decorated_label_name)
190
+ end
191
+
192
+ def decorated_label_name
193
+ name = case ActiveGraph::Config[:module_handling]
194
+ when :demodulize
195
+ self.name.demodulize
196
+ when Proc
197
+ ActiveGraph::Config[:module_handling].call self.name
198
+ else
199
+ self.name
200
+ end
201
+
202
+ name.to_sym
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end