neo4j 1.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +141 -0
- data/CONTRIBUTORS +15 -0
- data/Gemfile +3 -0
- data/README.rdoc +2015 -0
- data/lib/neo4j.old/batch_inserter.rb +144 -0
- data/lib/neo4j.old/config.rb +138 -0
- data/lib/neo4j.old/event_handler.rb +73 -0
- data/lib/neo4j.old/extensions/activemodel.rb +158 -0
- data/lib/neo4j.old/extensions/aggregate.rb +12 -0
- data/lib/neo4j.old/extensions/aggregate/aggregate_enum.rb +40 -0
- data/lib/neo4j.old/extensions/aggregate/ext/node_mixin.rb +69 -0
- data/lib/neo4j.old/extensions/aggregate/node_aggregate.rb +8 -0
- data/lib/neo4j.old/extensions/aggregate/node_aggregate_mixin.rb +331 -0
- data/lib/neo4j.old/extensions/aggregate/node_aggregator.rb +216 -0
- data/lib/neo4j.old/extensions/aggregate/node_group.rb +43 -0
- data/lib/neo4j.old/extensions/aggregate/prop_group.rb +30 -0
- data/lib/neo4j.old/extensions/aggregate/property_enum.rb +24 -0
- data/lib/neo4j.old/extensions/aggregate/props_aggregate.rb +8 -0
- data/lib/neo4j.old/extensions/aggregate/props_aggregate_mixin.rb +31 -0
- data/lib/neo4j.old/extensions/aggregate/props_aggregator.rb +80 -0
- data/lib/neo4j.old/extensions/find_path.rb +117 -0
- data/lib/neo4j.old/extensions/graph_algo.rb +1 -0
- data/lib/neo4j.old/extensions/graph_algo/all_simple_paths.rb +133 -0
- data/lib/neo4j.old/extensions/graph_algo/neo4j-graph-algo-0.3.jar +0 -0
- data/lib/neo4j.old/extensions/reindexer.rb +104 -0
- data/lib/neo4j.old/extensions/rest.rb +21 -0
- data/lib/neo4j.old/extensions/rest/rest.rb +336 -0
- data/lib/neo4j.old/extensions/rest/rest_mixin.rb +193 -0
- data/lib/neo4j.old/extensions/rest/server.rb +50 -0
- data/lib/neo4j.old/extensions/rest/stubs.rb +141 -0
- data/lib/neo4j.old/extensions/rest_master.rb +34 -0
- data/lib/neo4j.old/extensions/rest_slave.rb +31 -0
- data/lib/neo4j.old/extensions/tx_tracker.rb +392 -0
- data/lib/neo4j.old/indexer.rb +187 -0
- data/lib/neo4j.old/jars.rb +6 -0
- data/lib/neo4j.old/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j.old/jars/neo4j-kernel-1.0.jar +0 -0
- data/lib/neo4j.old/mixins/java_list_mixin.rb +139 -0
- data/lib/neo4j.old/mixins/java_node_mixin.rb +205 -0
- data/lib/neo4j.old/mixins/java_property_mixin.rb +169 -0
- data/lib/neo4j.old/mixins/java_relationship_mixin.rb +60 -0
- data/lib/neo4j.old/mixins/migration_mixin.rb +157 -0
- data/lib/neo4j.old/mixins/node_mixin.rb +249 -0
- data/lib/neo4j.old/mixins/property_class_methods.rb +265 -0
- data/lib/neo4j.old/mixins/rel_class_methods.rb +167 -0
- data/lib/neo4j.old/mixins/relationship_mixin.rb +103 -0
- data/lib/neo4j.old/neo.rb +247 -0
- data/lib/neo4j.old/node.rb +49 -0
- data/lib/neo4j.old/reference_node.rb +15 -0
- data/lib/neo4j.old/relationship.rb +85 -0
- data/lib/neo4j.old/relationships/decl_relationship_dsl.rb +164 -0
- data/lib/neo4j.old/relationships/has_list.rb +101 -0
- data/lib/neo4j.old/relationships/has_n.rb +129 -0
- data/lib/neo4j.old/relationships/node_traverser.rb +138 -0
- data/lib/neo4j.old/relationships/relationship_dsl.rb +149 -0
- data/lib/neo4j.old/relationships/traversal_position.rb +50 -0
- data/lib/neo4j.old/relationships/wrappers.rb +51 -0
- data/lib/neo4j.old/search_result.rb +72 -0
- data/lib/neo4j.old/transaction.rb +254 -0
- data/lib/neo4j.old/version.rb +3 -0
- data/lib/neo4j.rb +50 -0
- data/lib/neo4j/config.rb +137 -0
- data/lib/neo4j/database.rb +43 -0
- data/lib/neo4j/equal.rb +22 -0
- data/lib/neo4j/event_handler.rb +91 -0
- data/lib/neo4j/index.rb +157 -0
- data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j/jars/lucene-core-2.9.2.jar +0 -0
- data/lib/neo4j/jars/lucene-core-3.0.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-index-1.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-kernel-1.1.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-kernel-1.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-lucene-index-0.1-20100916.085626-67.jar +0 -0
- data/lib/neo4j/mapping/class_methods/index.rb +21 -0
- data/lib/neo4j/mapping/class_methods/property.rb +139 -0
- data/lib/neo4j/mapping/class_methods/relationship.rb +96 -0
- data/lib/neo4j/mapping/class_methods/rule.rb +135 -0
- data/lib/neo4j/mapping/decl_relationship_dsl.rb +151 -0
- data/lib/neo4j/mapping/has_n.rb +117 -0
- data/lib/neo4j/mapping/node_mixin.rb +70 -0
- data/lib/neo4j/neo4j.rb +65 -0
- data/lib/neo4j/node.rb +82 -0
- data/lib/neo4j/node_mixin.rb +4 -0
- data/lib/neo4j/node_relationship.rb +60 -0
- data/lib/neo4j/node_traverser.rb +141 -0
- data/lib/neo4j/property.rb +72 -0
- data/lib/neo4j/rails/lucene_connection_closer.rb +19 -0
- data/lib/neo4j/rails/model.rb +210 -0
- data/lib/neo4j/rails/railtie.rb +16 -0
- data/lib/neo4j/rails/transaction.rb +29 -0
- data/lib/neo4j/rails/value.rb +43 -0
- data/lib/neo4j/relationship.rb +88 -0
- data/lib/neo4j/relationship_traverser.rb +57 -0
- data/lib/neo4j/to_java.rb +17 -0
- data/lib/neo4j/transaction.rb +69 -0
- data/lib/neo4j/version.rb +3 -0
- data/neo4j.gemspec +30 -0
- metadata +243 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
module Neo4j
|
2
|
+
|
3
|
+
class BatchItem # :nodoc:
|
4
|
+
attr_accessor :_wrapper, :neo_id
|
5
|
+
|
6
|
+
include Neo4j::JavaPropertyMixin
|
7
|
+
|
8
|
+
def initialize(neo_id, inserter)
|
9
|
+
@neo_id = neo_id
|
10
|
+
@inserter = inserter
|
11
|
+
end
|
12
|
+
|
13
|
+
def getId(); neo_id end
|
14
|
+
|
15
|
+
def has_property?(key)
|
16
|
+
props.include?(key.to_s)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_property(key)
|
20
|
+
props[key]
|
21
|
+
end
|
22
|
+
|
23
|
+
def props
|
24
|
+
# not sure why I have to do it like this, Strange why I can't use the Java Hash ?
|
25
|
+
# gets java.lang.UnsupportedOperationException: null, in java/util/AbstractMap.java:186:in `put'
|
26
|
+
java_props = @inserter.getNodeProperties(neo_id)
|
27
|
+
ruby_props = {}
|
28
|
+
java_props.keySet().each{|k| ruby_props[k] = java_props[k]}
|
29
|
+
ruby_props
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def setProperty(key, value)
|
34
|
+
ruby_props = props
|
35
|
+
ruby_props[key.to_s] = value
|
36
|
+
@inserter.setNodeProperties(neo_id, ruby_props)
|
37
|
+
|
38
|
+
if (wrapper_class and key[0, 1] != '_') # do not want events on internal properties
|
39
|
+
wrapper_class.indexer.on_property_changed(wrapper, key)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Neo4j has a batch insert mode that drops support for transactions and concurrency in favor of insertion speed.
|
45
|
+
# This is useful when you have a big dataset that needs to be loaded once. In our experience, the batch inserter will
|
46
|
+
# typically inject data around five times faster than running in normal transactional mode.
|
47
|
+
#
|
48
|
+
# === Usage
|
49
|
+
#
|
50
|
+
# The initialize method takes a code block that will use the BatchInserter.
|
51
|
+
#
|
52
|
+
# Neo4j::BatchInserter.new do |b|
|
53
|
+
# a = Neo4j::Node.new :name => 'a'
|
54
|
+
# b = Neo4j::Node.new :name => 'b'
|
55
|
+
# c = Foo.new :key1 => 'val1', :key2 => 'val2'
|
56
|
+
# c[:name] = "c"
|
57
|
+
# Neo4j::Relationship.new(:friend, a, b, :since => '2001-01-01')
|
58
|
+
# Neo4j::Relationship.new(:friend, Neo4j.ref_node, c, :since => '2001-01-01')
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# After the code block the normal creation for nodes and relationship will be used.
|
62
|
+
# Traversals inside the batch inserter block is not possible.
|
63
|
+
# The BatchInserter can be used together with Neo4j Migrations (see Neo4j#migration)
|
64
|
+
#
|
65
|
+
class BatchInserter
|
66
|
+
|
67
|
+
# See class description for usage.
|
68
|
+
#
|
69
|
+
# === Parameters
|
70
|
+
# storage_path:: optional, the location of the neo4j dabase on file system, default Neo4j::Config[:storage_path]
|
71
|
+
# db_version:: optional, sets version number on reference node, default nil -> do not set this property
|
72
|
+
def initialize(storage_path = Neo4j::Config[:storage_path], db_version=nil) # :yields: batch_inserter
|
73
|
+
# create the batch inserter
|
74
|
+
inserter = org.neo4j.kernel.impl.batchinsert.BatchInserterImpl.new(storage_path)
|
75
|
+
|
76
|
+
# save original methods
|
77
|
+
create_node_meth = Neo4j.method(:create_node)
|
78
|
+
create_rel_meth = Neo4j.method(:create_rel)
|
79
|
+
ref_node_meth = Neo4j.method(:ref_node)
|
80
|
+
instance_meth = Neo4j.method(:instance)
|
81
|
+
|
82
|
+
# replace methods
|
83
|
+
neo4j_meta = (class << Neo4j; self; end)
|
84
|
+
neo4j_meta.instance_eval do
|
85
|
+
define_method(:create_node) do |props|
|
86
|
+
props ||= {}
|
87
|
+
id = inserter.createNode(props.keys.inject({}) {|hash, key| hash[key.to_s] = props[key]; hash})
|
88
|
+
BatchItem.new(id, inserter)
|
89
|
+
end
|
90
|
+
define_method(:create_rel) do |type, from_node, to_node, props|
|
91
|
+
props = Hash[*props.map{|k, v| [k.to_s, v]}.flatten] if props
|
92
|
+
java_type = org.neo4j.graphdb.DynamicRelationshipType.withName(type.to_s)
|
93
|
+
id = inserter.createRelationship(from_node.neo_id, to_node.neo_id, java_type, props)
|
94
|
+
BatchItem.new(id, inserter)
|
95
|
+
end
|
96
|
+
define_method(:ref_node) do
|
97
|
+
BatchItem.new(inserter.getReferenceNode, inserter)
|
98
|
+
end
|
99
|
+
define_method(:instance) do
|
100
|
+
Neo4j::BatchInstance.new
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
begin
|
105
|
+
yield inserter
|
106
|
+
Neo4j.ref_node[:db_version] = db_version if db_version
|
107
|
+
ensure
|
108
|
+
inserter.shutdown
|
109
|
+
# restore old methods
|
110
|
+
neo4j_meta.instance_eval do
|
111
|
+
define_method(:create_node, create_node_meth)
|
112
|
+
define_method(:create_rel, create_rel_meth)
|
113
|
+
define_method(:ref_node, ref_node_meth)
|
114
|
+
define_method(:instance, instance_meth)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# This method is used if the batch inserter is used from the Migration API.
|
120
|
+
#
|
121
|
+
# === Parameters
|
122
|
+
# context:: the context on which the batch inserter code block is evaluated in, not used.
|
123
|
+
# version:: optional, if given then will set the property db_version on the context
|
124
|
+
def self.execute(context, version=nil, &block)
|
125
|
+
# Neo4j must not be running while using batch inserter, stop it just in case ...
|
126
|
+
Neo4j::Transaction.finish
|
127
|
+
Neo4j.stop
|
128
|
+
|
129
|
+
BatchInserter.new(Neo4j::Config[:storage_path], version, &block)
|
130
|
+
|
131
|
+
Neo4j.start
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Used instead of Neo4j.instance object - will happily accept any methods - like transaction methods.
|
136
|
+
class BatchInstance # :nodoc:
|
137
|
+
def method_missing(m, *args, &block)
|
138
|
+
return BatchInstance.new
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
|
@@ -0,0 +1,138 @@
|
|
1
|
+
|
2
|
+
module Neo4j
|
3
|
+
|
4
|
+
|
5
|
+
# Keeps configuration for neo4j.
|
6
|
+
#
|
7
|
+
# Neo4j::Config[:storage_path]:: is used for locating the neo4j database on the filesystem.
|
8
|
+
# Neo4j::Config[:rest_port]:: used by the REST extension for starting a web server on a port
|
9
|
+
#
|
10
|
+
class Config
|
11
|
+
# This code is copied from merb-core/config.rb.
|
12
|
+
class << self
|
13
|
+
# Returns the hash of default config values for neo4j
|
14
|
+
#
|
15
|
+
# ==== Returns
|
16
|
+
# Hash:: The defaults for the config.
|
17
|
+
def defaults
|
18
|
+
@defaults ||= {
|
19
|
+
:storage_path => 'tmp/neo4j',
|
20
|
+
:rest_port => 9123
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Yields the configuration.
|
26
|
+
#
|
27
|
+
# ==== Block parameters
|
28
|
+
# c<Hash>:: The configuration parameters.
|
29
|
+
#
|
30
|
+
# ==== Examples
|
31
|
+
# Neo4j::Config.use do |config|
|
32
|
+
# config[:storage_path] = '/var/neo4j'
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# ==== Returns
|
36
|
+
# nil
|
37
|
+
def use
|
38
|
+
@configuration ||= {}
|
39
|
+
yield @configuration
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Set the value of a config entry.
|
45
|
+
#
|
46
|
+
# ==== Parameters
|
47
|
+
# key<Object>:: The key to set the parameter for.
|
48
|
+
# val<Object>:: The value of the parameter.
|
49
|
+
#
|
50
|
+
def []=(key, val)
|
51
|
+
(@configuration ||= setup)[key] = val
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# Gets the the value of a config entry
|
56
|
+
#
|
57
|
+
# ==== Parameters
|
58
|
+
# key<Object>:: The key of the config entry value we want
|
59
|
+
#
|
60
|
+
def [](key)
|
61
|
+
(@configuration ||= setup)[key]
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Remove the value of a config entry.
|
66
|
+
#
|
67
|
+
# ==== Parameters
|
68
|
+
# key<Object>:: The key of the parameter to delete.
|
69
|
+
#
|
70
|
+
# ==== Returns
|
71
|
+
# Object:: The value of the removed entry.
|
72
|
+
#
|
73
|
+
def delete(key)
|
74
|
+
@configuration.delete(key)
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
# Remove all configuration. This can be useful for testing purpose.
|
79
|
+
#
|
80
|
+
#
|
81
|
+
# ==== Returns
|
82
|
+
# nil
|
83
|
+
#
|
84
|
+
def delete_all
|
85
|
+
@configuration = nil
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# Retrieve the value of a config entry, returning the provided default if the key is not present
|
90
|
+
#
|
91
|
+
# ==== Parameters
|
92
|
+
# key<Object>:: The key to retrieve the parameter for.
|
93
|
+
# default<Object>::
|
94
|
+
# The default value to return if the parameter is not set.
|
95
|
+
#
|
96
|
+
# ==== Returns
|
97
|
+
# Object:: The value of the configuration parameter or the default.
|
98
|
+
#
|
99
|
+
def fetch(key, default)
|
100
|
+
@configuration.fetch(key, default)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Sets up the configuration
|
104
|
+
#
|
105
|
+
# ==== Returns
|
106
|
+
# The configuration as a hash.
|
107
|
+
#
|
108
|
+
def setup()
|
109
|
+
@configuration = {}
|
110
|
+
@configuration.merge!(defaults)
|
111
|
+
@configuration
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
# Returns the configuration as a hash.
|
116
|
+
#
|
117
|
+
# ==== Returns
|
118
|
+
# Hash:: The config as a hash.
|
119
|
+
#
|
120
|
+
# :api: public
|
121
|
+
def to_hash
|
122
|
+
@configuration
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns the config as YAML.
|
126
|
+
#
|
127
|
+
# ==== Returns
|
128
|
+
# String:: The config as YAML.
|
129
|
+
#
|
130
|
+
# :api: public
|
131
|
+
def to_yaml
|
132
|
+
require "yaml"
|
133
|
+
@configuration.to_yaml
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Neo4j
|
2
|
+
|
3
|
+
# Handles events like a new node is created or deleted
|
4
|
+
class EventHandler
|
5
|
+
def initialize
|
6
|
+
@listeners = []
|
7
|
+
@filter_classes = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(listener)
|
11
|
+
@listeners << listener unless @listeners.include?(listener)
|
12
|
+
add_filter(listener) # the listener do not want to get events on it self
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove(listener)
|
16
|
+
@listeners.delete(listener)
|
17
|
+
end
|
18
|
+
|
19
|
+
def remove_all
|
20
|
+
@listeners = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def print
|
24
|
+
puts "Listeners #{@listeners.size}"
|
25
|
+
@listeners.each {|li| puts " Listener '#{li}'"}
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_filter(filter_class)
|
29
|
+
@filter_classes << filter_class unless @filter_classes.include?(filter_class)
|
30
|
+
end
|
31
|
+
|
32
|
+
def remove_filter(filter_class)
|
33
|
+
@filter_classes.delete filter_class
|
34
|
+
end
|
35
|
+
|
36
|
+
def node_created(node)
|
37
|
+
return if @filter_classes.include?(node.class)
|
38
|
+
@listeners.each {|li| li.on_node_created(node) if li.respond_to?(:on_node_created)}
|
39
|
+
end
|
40
|
+
|
41
|
+
def node_deleted(node)
|
42
|
+
return if @filter_classes.include?(node.class)
|
43
|
+
@listeners.each {|li| li.on_node_deleted(node) if li.respond_to?(:on_node_deleted)}
|
44
|
+
end
|
45
|
+
|
46
|
+
def relationship_created(relationship)
|
47
|
+
return if @filter_classes.include?(relationship.class)
|
48
|
+
@listeners.each {|li| li.on_relationship_created(relationship) if li.respond_to?(:on_relationship_created)}
|
49
|
+
end
|
50
|
+
|
51
|
+
def relationship_deleted(relationship)
|
52
|
+
return if @filter_classes.include?(relationship.class)
|
53
|
+
@listeners.each {|li| li.on_relationship_deleted(relationship) if li.respond_to?(:on_relationship_deleted)}
|
54
|
+
end
|
55
|
+
|
56
|
+
def property_changed(node, key, old_value, new_value)
|
57
|
+
return if @filter_classes.include?(node.class)
|
58
|
+
@listeners.each {|li| li.on_property_changed(node, key, old_value, new_value) if li.respond_to?(:on_property_changed)}
|
59
|
+
end
|
60
|
+
|
61
|
+
def tx_finished(tx)
|
62
|
+
@listeners.each {|li| li.on_tx_finished(tx) if li.respond_to?(:on_tx_finished)}
|
63
|
+
end
|
64
|
+
|
65
|
+
def neo_started(neo_instance)
|
66
|
+
@listeners.each {|li| li.on_neo_started(neo_instance) if li.respond_to?(:on_neo_started)}
|
67
|
+
end
|
68
|
+
|
69
|
+
def neo_stopped(neo_instance)
|
70
|
+
@listeners.each {|li| li.on_neo_stopped(neo_instance) if li.respond_to?(:on_neo_stopped)}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'singleton'
|
3
|
+
require 'neo4j'
|
4
|
+
require 'active_model'
|
5
|
+
|
6
|
+
|
7
|
+
module Neo4j::NodeMixin
|
8
|
+
def to_model
|
9
|
+
Neo4j::ActiveModel::ActiveModelFactory.instance.to_model(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def attributes
|
13
|
+
attr = props
|
14
|
+
attr.keys.each {|k| attr.delete k if k[0] == ?_}
|
15
|
+
attr
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
module Neo4j::ActiveModel
|
21
|
+
|
22
|
+
def self.on_property_changed(node, key, old_value, new_value)
|
23
|
+
# make model dirty since it is changed
|
24
|
+
ActiveModelFactory.instance.dirty_node!(node.neo_id)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.on_tx_finished(tx)
|
28
|
+
# make all models clean again
|
29
|
+
ActiveModelFactory.instance.clean!
|
30
|
+
end
|
31
|
+
|
32
|
+
class ActiveModelFactory
|
33
|
+
private
|
34
|
+
def initialize
|
35
|
+
@classes = {}
|
36
|
+
@node_models = {}
|
37
|
+
Thread.current[:neo4j_active_model_factory] = self
|
38
|
+
Neo4j.event_handler.add(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
public
|
42
|
+
def self.instance
|
43
|
+
# create one Neo4jActiveModelFactory for each thread
|
44
|
+
# since a transaction belongs to a thread and we don't want
|
45
|
+
# side effect of one transaction making model object dirty or clean for a different transaction
|
46
|
+
# in a different thread.
|
47
|
+
Thread.current[:neo4j_active_model_factory] || ActiveModelFactory.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def dirty_node!(neo_id)
|
51
|
+
@node_models[neo_id] && @node_models[neo_id].dirty!
|
52
|
+
end
|
53
|
+
|
54
|
+
def clean!
|
55
|
+
@node_models.clear
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_model(obj)
|
59
|
+
@node_models[obj.neo_id] || create_model_for(obj)
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_model_for(obj)
|
63
|
+
clazz = @classes[obj.class] || create_wrapped_class_for(obj)
|
64
|
+
@node_models[obj.neo_id] = clazz.new(obj)
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_wrapped_class_for(obj)
|
68
|
+
clazz = Class.new do
|
69
|
+
def initialize(wrapped)
|
70
|
+
@dirty = false
|
71
|
+
@wrapped = wrapped
|
72
|
+
end
|
73
|
+
|
74
|
+
def dirty!
|
75
|
+
@dirty = true
|
76
|
+
end
|
77
|
+
|
78
|
+
def persisted?
|
79
|
+
! @dirty
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_key
|
83
|
+
persisted? ? @wrapped.neo_id : nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_param
|
87
|
+
to_key
|
88
|
+
end
|
89
|
+
|
90
|
+
if obj.respond_to?(:errors)
|
91
|
+
def errors;
|
92
|
+
@wrapped.errors;
|
93
|
+
end
|
94
|
+
else
|
95
|
+
def errors
|
96
|
+
object = Object.new
|
97
|
+
|
98
|
+
def object.[](key)
|
99
|
+
[]
|
100
|
+
end
|
101
|
+
|
102
|
+
def object.full_messages()
|
103
|
+
[]
|
104
|
+
end
|
105
|
+
|
106
|
+
object
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
if obj.respond_to?(:valid?)
|
111
|
+
def valid?;
|
112
|
+
@wrapped.valid?;
|
113
|
+
end
|
114
|
+
else
|
115
|
+
def valid?
|
116
|
+
true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
singleton = class << clazz;
|
122
|
+
self;
|
123
|
+
end
|
124
|
+
singleton.class_eval do
|
125
|
+
# class methods
|
126
|
+
define_method :model_name do
|
127
|
+
@_model_name ||= ActiveModel::Name.new(obj.class)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
@classes[obj.class] = clazz
|
132
|
+
clazz
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
Neo4j.event_handler.add(self)
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
#class LintTest < ActiveModel::TestCase
|
143
|
+
# include ActiveModel::Lint::Tests
|
144
|
+
#
|
145
|
+
# class MyModel
|
146
|
+
# include Neo4j::NodeMixin
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# def setup
|
150
|
+
# @model = MyModel.new
|
151
|
+
# end
|
152
|
+
#
|
153
|
+
#end
|
154
|
+
#
|
155
|
+
#require 'test/unit/ui/console/testrunner'
|
156
|
+
#Neo4j::Transaction.run do
|
157
|
+
# Test::Unit::UI::Console::TestRunner.run(LintTest)
|
158
|
+
#end
|