neo4j 3.0.0.rc.3 → 3.0.0.rc.4
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 +10 -0
- data/Gemfile +5 -4
- data/README.md +1 -1
- data/config/neo4j/add_classnames.yml +1 -0
- data/lib/neo4j.rb +2 -0
- data/lib/neo4j/active_node.rb +4 -1
- data/lib/neo4j/active_node/has_n.rb +75 -9
- data/lib/neo4j/active_node/has_n/association.rb +5 -4
- data/lib/neo4j/active_node/id_property.rb +50 -5
- data/lib/neo4j/active_node/initialize.rb +1 -0
- data/lib/neo4j/active_node/labels.rb +15 -3
- data/lib/neo4j/active_node/orm_adapter.rb +1 -1
- data/lib/neo4j/active_node/persistence.rb +39 -0
- data/lib/neo4j/active_node/query/query_proxy.rb +29 -6
- data/lib/neo4j/active_node/query/query_proxy_find_in_batches.rb +20 -0
- data/lib/neo4j/active_node/query/query_proxy_methods.rb +24 -12
- data/lib/neo4j/active_node/query_methods.rb +21 -10
- data/lib/neo4j/active_node/reflection.rb +85 -0
- data/lib/neo4j/active_rel/callbacks.rb +3 -1
- data/lib/neo4j/active_rel/initialize.rb +2 -2
- data/lib/neo4j/active_rel/persistence.rb +23 -14
- data/lib/neo4j/active_rel/property.rb +9 -10
- data/lib/neo4j/active_rel/query.rb +51 -29
- data/lib/neo4j/active_rel/related_node.rb +2 -6
- data/lib/neo4j/migration.rb +185 -0
- data/lib/neo4j/paginated.rb +2 -1
- data/lib/neo4j/railtie.rb +13 -8
- data/lib/neo4j/shared/persistence.rb +10 -56
- data/lib/neo4j/shared/property.rb +15 -6
- data/lib/neo4j/tasks/migration.rake +23 -0
- data/lib/neo4j/version.rb +1 -1
- metadata +7 -2
@@ -3,7 +3,6 @@ module Neo4j::ActiveRel
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
-
include Enumerable
|
7
6
|
|
8
7
|
# Returns the object with the specified neo4j id.
|
9
8
|
# @param [String,Fixnum] id of node to find
|
@@ -13,54 +12,77 @@ module Neo4j::ActiveRel
|
|
13
12
|
find_by_id(id, session)
|
14
13
|
end
|
15
14
|
|
15
|
+
# Loads the relationship using its neo_id.
|
16
16
|
def find_by_id(key, session = Neo4j::Session.current!)
|
17
17
|
Neo4j::Relationship.load(key.to_i, session)
|
18
18
|
end
|
19
19
|
|
20
|
-
#
|
20
|
+
# Performs a very basic match on the relationship.
|
21
|
+
# This is not executed lazily, it will immediately return matching objects.
|
22
|
+
# To use a string, prefix the property with "r1"
|
23
|
+
# @example Match with a string
|
24
|
+
# MyRelClass.where('r1.grade > r1')
|
21
25
|
def where(args={})
|
22
|
-
|
23
|
-
Neo4j::Session.query("MATCH n1-[r1:`#{self._type}`]->(#{cypher_node_string(:inbound)}) WHERE #{where_string(args)} RETURN r1")
|
24
|
-
else
|
25
|
-
self._from_class.query_as(:n1).match("(#{cypher_node_string(:outbound)})-[r1:`#{self._type}`]->(#{cypher_node_string(:inbound)})").where(Hash["r1" => args])
|
26
|
-
end
|
27
|
-
return self
|
26
|
+
Neo4j::Session.query.match("#{cypher_string(:outbound)}-[r1:`#{self._type}`]->#{cypher_string(:inbound)}").where(where_string(args)).pluck(:r1)
|
28
27
|
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
@query.pluck(:r1)
|
35
|
-
end.each {|r| yield r }
|
29
|
+
# Performs a basic match on the relationship, returning all results.
|
30
|
+
# This is not executed lazily, it will immediately return matching objects.
|
31
|
+
def all
|
32
|
+
all_query.pluck(:r1)
|
36
33
|
end
|
37
34
|
|
38
35
|
def first
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
36
|
+
all_query.limit(1).order("ID(r1)").pluck(:r1).first
|
37
|
+
end
|
38
|
+
|
39
|
+
def last
|
40
|
+
all_query.limit(1).order("ID(r1) DESC").pluck(:r1).first
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def all_query
|
46
|
+
Neo4j::Session.query.match("#{cypher_string}-[r1:`#{self._type}`]->#{cypher_string(:inbound)}")
|
44
47
|
end
|
45
48
|
|
46
|
-
def
|
49
|
+
def cypher_string(dir = :outbound)
|
47
50
|
case dir
|
48
51
|
when :outbound
|
49
|
-
|
52
|
+
identifier = '(n1'
|
53
|
+
identifier + (_from_class == :any ? ')' : cypher_label(:outbound))
|
50
54
|
when :inbound
|
51
|
-
|
52
|
-
|
53
|
-
|
55
|
+
identifier = '(n2'
|
56
|
+
identifier + (_to_class == :any ? ')' : cypher_label(:inbound))
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
|
-
|
60
|
+
def cypher_label(dir = :outbound)
|
61
|
+
target_class = dir == :outbound ? as_constant(_from_class) : as_constant(_to_class)
|
62
|
+
":`#{target_class.mapped_label_name}`)"
|
63
|
+
end
|
64
|
+
|
65
|
+
def as_constant(given_class)
|
66
|
+
case
|
67
|
+
when given_class.is_a?(String)
|
68
|
+
given_class.constantize
|
69
|
+
when given_class.is_a?(Symbol)
|
70
|
+
given_class.to_s.constantize
|
71
|
+
else
|
72
|
+
given_class
|
73
|
+
end
|
74
|
+
end
|
57
75
|
|
58
76
|
def where_string(args)
|
59
|
-
args.
|
60
|
-
|
61
|
-
|
77
|
+
if args.is_a?(Hash)
|
78
|
+
args.map do |k, v|
|
79
|
+
v.is_a?(Integer) ? "r1.#{k} = #{v}" : "r1.#{k} = '#{v}'"
|
80
|
+
end.join(', ')
|
81
|
+
else
|
82
|
+
args
|
83
|
+
end
|
62
84
|
end
|
63
85
|
|
64
86
|
end
|
65
87
|
end
|
66
|
-
end
|
88
|
+
end
|
@@ -2,14 +2,10 @@ module Neo4j::ActiveRel
|
|
2
2
|
# A container for ActiveRel's :inbound and :outbound methods. It provides lazy loading of nodes.
|
3
3
|
class RelatedNode
|
4
4
|
|
5
|
-
class InvalidParameterError < StandardError
|
6
|
-
def message
|
7
|
-
'RelatedNode must be initialized with either a node ID or node'
|
8
|
-
end
|
9
|
-
end
|
5
|
+
class InvalidParameterError < StandardError; end
|
10
6
|
|
11
7
|
def initialize(node = nil)
|
12
|
-
@node = valid_node_param?(node) ? node : (raise InvalidParameterError
|
8
|
+
@node = valid_node_param?(node) ? node : (raise InvalidParameterError, 'RelatedNode must be initialized with either a node ID or node' )
|
13
9
|
end
|
14
10
|
|
15
11
|
def == (obj)
|
@@ -0,0 +1,185 @@
|
|
1
|
+
module Neo4j
|
2
|
+
class Migration
|
3
|
+
class AddIdProperty < Neo4j::Migration
|
4
|
+
attr_reader :models_filename
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@models_filename = File.join(Rails.root.join('db', 'neo4j-migrate'), 'add_id_property.yml')
|
8
|
+
end
|
9
|
+
|
10
|
+
def migrate
|
11
|
+
models = ActiveSupport::HashWithIndifferentAccess.new(YAML.load_file(models_filename))[:models]
|
12
|
+
puts "This task will add an ID Property every node in the given file."
|
13
|
+
puts "It may take a significant amount of time, please be patient."
|
14
|
+
models.each do |model|
|
15
|
+
puts
|
16
|
+
puts
|
17
|
+
puts "Adding IDs to #{model}"
|
18
|
+
add_ids_to model.constantize
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup
|
23
|
+
FileUtils.mkdir_p("db/neo4j-migrate")
|
24
|
+
unless File.file?(models_filename)
|
25
|
+
File.open(models_filename, 'w') do |file|
|
26
|
+
file.write("# Provide models to which IDs should be added.\n# It will only modify nodes that do not have IDs. There is no danger of overwriting data.\n# models: [Student,Lesson,Teacher,Exam]\nmodels: []")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def add_ids_to(model)
|
34
|
+
require 'benchmark'
|
35
|
+
|
36
|
+
max_per_batch = (ENV['MAX_PER_BATCH'] || default_max_per_batch).to_i
|
37
|
+
|
38
|
+
label = model.mapped_label_name
|
39
|
+
property = model.primary_key
|
40
|
+
nodes_left = 1
|
41
|
+
last_time_taken = nil
|
42
|
+
|
43
|
+
until nodes_left == 0
|
44
|
+
nodes_left = Neo4j::Session.query.match(n: label).where("NOT has(n.#{property})").return("COUNT(n) AS ids").first.ids
|
45
|
+
|
46
|
+
time_per_node = last_time_taken / max_per_batch if last_time_taken
|
47
|
+
print "Running first batch...\r"
|
48
|
+
if time_per_node
|
49
|
+
eta_seconds = (nodes_left * time_per_node).round
|
50
|
+
print "#{nodes_left} nodes left. Last batch: #{(time_per_node * 1000.0).round(1)}ms / node (ETA: #{eta_seconds / 60} minutes)\r"
|
51
|
+
end
|
52
|
+
|
53
|
+
return if nodes_left == 0
|
54
|
+
to_set = [nodes_left, max_per_batch].min
|
55
|
+
|
56
|
+
new_ids = to_set.times.map { new_id_for(model) }
|
57
|
+
begin
|
58
|
+
last_time_taken = id_batch_set(label, property, new_ids, to_set)
|
59
|
+
rescue Neo4j::Server::CypherResponse::ResponseError, Faraday::TimeoutError
|
60
|
+
new_max_per_batch = (max_per_batch * 0.8).round
|
61
|
+
puts "Error querying #{max_per_batch} nodes. Trying #{new_max_per_batch}"
|
62
|
+
max_per_batch = new_max_per_batch
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def id_batch_set(label, property, new_ids, to_set)
|
68
|
+
Benchmark.realtime do
|
69
|
+
Neo4j::Transaction.run do
|
70
|
+
Neo4j::Session.query("MATCH (n:`#{label}`) WHERE NOT has(n.#{property})
|
71
|
+
with COLLECT(n) as nodes, #{new_ids} as ids
|
72
|
+
FOREACH(i in range(0,#{to_set - 1})|
|
73
|
+
FOREACH(node in [nodes[i]]|
|
74
|
+
SET node.#{property} = ids[i]))
|
75
|
+
RETURN distinct(true)
|
76
|
+
LIMIT #{to_set}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def default_max_per_batch
|
82
|
+
900
|
83
|
+
end
|
84
|
+
|
85
|
+
def new_id_for(model)
|
86
|
+
if model.id_property_info[:type][:auto]
|
87
|
+
SecureRandom::uuid
|
88
|
+
else
|
89
|
+
model.new.send(model.id_property_info[:type][:on])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class AddClassnames < Neo4j::Migration
|
95
|
+
attr_reader :classnames_filename, :classnames_filepath
|
96
|
+
|
97
|
+
def initialize
|
98
|
+
@classnames_filename = 'add_classnames.yml'
|
99
|
+
@classnames_filepath = File.join(Rails.root.join('db', 'neo4j-migrate'), classnames_filename)
|
100
|
+
end
|
101
|
+
|
102
|
+
def migrate
|
103
|
+
puts "Adding classnames. This make take some time."
|
104
|
+
execute(true)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test
|
108
|
+
puts "TESTING! No queries will be executed."
|
109
|
+
execute(false)
|
110
|
+
end
|
111
|
+
|
112
|
+
def setup
|
113
|
+
puts "Creating file #{classnames_filepath}. Please use this as the migration guide."
|
114
|
+
FileUtils.mkdir_p("db/neo4j-migrate")
|
115
|
+
unless File.file?(@classnames_filepath)
|
116
|
+
source = File.join(File.dirname(__FILE__), "..", "..", "config", "neo4j", classnames_filename)
|
117
|
+
FileUtils.copy_file(source, classnames_filepath)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def execute(migrate = false)
|
124
|
+
file_init
|
125
|
+
map = []
|
126
|
+
map.push :nodes if @model_map[:nodes]
|
127
|
+
map.push :relationships if @model_map[:relationships]
|
128
|
+
map.each do |type|
|
129
|
+
@model_map[type].each do |action, labels|
|
130
|
+
do_classnames(action, labels, type, migrate)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def do_classnames(action, labels, type, migrate = false)
|
136
|
+
method = type == :nodes ? :node_cypher : :rel_cypher
|
137
|
+
labels.each do |label|
|
138
|
+
puts cypher = self.send(method, label, action)
|
139
|
+
execute_cypher(cypher) if migrate
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def file_init
|
144
|
+
@model_map = ActiveSupport::HashWithIndifferentAccess.new(YAML.load_file(classnames_filepath))
|
145
|
+
end
|
146
|
+
|
147
|
+
def node_cypher(label, action)
|
148
|
+
where, phrase_start = action_variables(action, 'n')
|
149
|
+
puts "#{phrase_start} _classname '#{label}' on nodes with matching label:"
|
150
|
+
"MATCH (n:`#{label}`) #{where} SET n._classname = '#{label}' RETURN COUNT(n) as modified"
|
151
|
+
end
|
152
|
+
|
153
|
+
def rel_cypher(hash, action)
|
154
|
+
label = hash[0]
|
155
|
+
value = hash[1]
|
156
|
+
from = value[:from]
|
157
|
+
raise "All relationships require a 'type'" unless value[:type]
|
158
|
+
|
159
|
+
from_cypher = from ? "(from:`#{from}`)" : "(from)"
|
160
|
+
to = value[:to]
|
161
|
+
to_cypher = to ? "(to:`#{to}`)" : "(to)"
|
162
|
+
type = "[r:`#{value[:type]}`]"
|
163
|
+
where, phrase_start = action_variables(action, 'r')
|
164
|
+
puts "#{phrase_start} _classname '#{label}' where type is '#{value[:type]}' using cypher:"
|
165
|
+
"MATCH #{from_cypher}-#{type}->#{to_cypher} #{where} SET r._classname = '#{label}' return COUNT(r) as modified"
|
166
|
+
end
|
167
|
+
|
168
|
+
def execute_cypher(query_string)
|
169
|
+
puts "Modified #{Neo4j::Session.query(query_string).first.modified} records"
|
170
|
+
puts ""
|
171
|
+
end
|
172
|
+
|
173
|
+
def action_variables(action, identifier)
|
174
|
+
case action
|
175
|
+
when 'overwrite'
|
176
|
+
['', 'Overwriting']
|
177
|
+
when 'add'
|
178
|
+
["WHERE NOT HAS(#{identifier}._classname)", 'Adding']
|
179
|
+
else
|
180
|
+
raise "Invalid action #{action} specified"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
data/lib/neo4j/paginated.rb
CHANGED
@@ -10,10 +10,11 @@ module Neo4j
|
|
10
10
|
def self.create_from(source, page, per_page)
|
11
11
|
#partial = source.drop((page-1) * per_page).first(per_page)
|
12
12
|
partial = source.skip(page-1).limit(per_page)
|
13
|
-
Paginated.new(partial, source.
|
13
|
+
Paginated.new(partial, source.count, page)
|
14
14
|
end
|
15
15
|
|
16
16
|
delegate :each, :to => :items
|
17
|
+
delegate :pluck, :to => :items
|
17
18
|
delegate :size, :[], :to => :items
|
18
19
|
end
|
19
20
|
end
|
data/lib/neo4j/railtie.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'active_support/notifications'
|
2
|
+
require 'rails/railtie'
|
2
3
|
|
3
4
|
module Neo4j
|
4
|
-
|
5
|
+
class Railtie < ::Rails::Railtie
|
5
6
|
config.neo4j = ActiveSupport::OrderedOptions.new
|
6
7
|
|
7
8
|
# Add ActiveModel translations to the I18n load_path
|
@@ -9,6 +10,11 @@ module Neo4j
|
|
9
10
|
config.i18n.load_path += Dir[File.join(File.dirname(__FILE__), '..', '..', '..', 'config', 'locales', '*.{rb,yml}')]
|
10
11
|
end
|
11
12
|
|
13
|
+
rake_tasks do
|
14
|
+
load 'neo4j/tasks/neo4j_server.rake'
|
15
|
+
load 'neo4j/tasks/migration.rake'
|
16
|
+
end
|
17
|
+
|
12
18
|
class << self
|
13
19
|
def java_platform?
|
14
20
|
RUBY_PLATFORM =~ /java/
|
@@ -26,7 +32,7 @@ module Neo4j
|
|
26
32
|
end
|
27
33
|
|
28
34
|
if cfg.sessions.empty?
|
29
|
-
cfg.sessions << {type: cfg.session_type, path: cfg.session_path, options: cfg.session_options}
|
35
|
+
cfg.sessions << { type: cfg.session_type, path: cfg.session_path, options: cfg.session_options }
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
@@ -45,18 +51,17 @@ module Neo4j
|
|
45
51
|
raise "Tried to start embedded Neo4j db without using JRuby (got #{RUBY_PLATFORM}), please run `rvm jruby`"
|
46
52
|
end
|
47
53
|
|
48
|
-
if
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
54
|
+
session = if session_opts.key?(:name)
|
55
|
+
Neo4j::Session.open_named(session_opts[:type], session_opts[:name], session_opts[:default], session_opts[:path])
|
56
|
+
else
|
57
|
+
Neo4j::Session.open(session_opts[:type], session_opts[:path], session_opts[:options])
|
58
|
+
end
|
53
59
|
|
54
60
|
start_embedded_session(session) if session_opts[:type] == :embedded_db
|
55
61
|
end
|
56
62
|
|
57
63
|
end
|
58
64
|
|
59
|
-
|
60
65
|
# Starting Neo after :load_config_initializers allows apps to
|
61
66
|
# register migrations in config/initializers
|
62
67
|
initializer "neo4j.start", :after => :load_config_initializers do |app|
|
@@ -1,45 +1,9 @@
|
|
1
1
|
module Neo4j::Shared
|
2
2
|
module Persistence
|
3
3
|
|
4
|
-
class RecordInvalidError < RuntimeError
|
5
|
-
attr_reader :record
|
6
|
-
|
7
|
-
def initialize(record)
|
8
|
-
@record = record
|
9
|
-
super(@record.errors.full_messages.join(", "))
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
4
|
extend ActiveSupport::Concern
|
14
5
|
include Neo4j::TypeConverters
|
15
6
|
|
16
|
-
# Saves the model.
|
17
|
-
#
|
18
|
-
# If the model is new a record gets created in the database, otherwise the existing record gets updated.
|
19
|
-
# If perform_validation is true validations run.
|
20
|
-
# If any of them fail the action is cancelled and save returns false. If the flag is false validations are bypassed altogether. See ActiveRecord::Validations for more information.
|
21
|
-
# There’s a series of callbacks associated with save. If any of the before_* callbacks return false the action is cancelled and save returns false.
|
22
|
-
def save(*)
|
23
|
-
update_magic_properties
|
24
|
-
create_or_update
|
25
|
-
end
|
26
|
-
|
27
|
-
# Persist the object to the database. Validations and Callbacks are included
|
28
|
-
# by default but validation can be disabled by passing :validate => false
|
29
|
-
# to #save! Creates a new transaction.
|
30
|
-
#
|
31
|
-
# @raise a RecordInvalidError if there is a problem during save.
|
32
|
-
# @param (see Neo4j::Rails::Validations#save)
|
33
|
-
# @return nil
|
34
|
-
# @see #save
|
35
|
-
# @see Neo4j::Rails::Validations Neo4j::Rails::Validations - for the :validate parameter
|
36
|
-
# @see Neo4j::Rails::Callbacks Neo4j::Rails::Callbacks - for callbacks
|
37
|
-
def save!(*args)
|
38
|
-
unless save(*args)
|
39
|
-
raise RecordInvalidError.new(self)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
7
|
def update_model
|
44
8
|
if changed_attributes && !changed_attributes.empty?
|
45
9
|
changed_props = attributes.select{|k,v| changed_attributes.include?(k)}
|
@@ -49,7 +13,6 @@ module Neo4j::Shared
|
|
49
13
|
end
|
50
14
|
end
|
51
15
|
|
52
|
-
|
53
16
|
# Convenience method to set attribute and #save at the same time
|
54
17
|
# @param [Symbol, String] attribute of the attribute to update
|
55
18
|
# @param [Object] value to set
|
@@ -66,13 +29,6 @@ module Neo4j::Shared
|
|
66
29
|
self.save!
|
67
30
|
end
|
68
31
|
|
69
|
-
# Convenience method to set multiple attributes and #save at the same time
|
70
|
-
# @param [Hash] attributes of names and values of attributes to set
|
71
|
-
def update_attributes(attributes)
|
72
|
-
assign_attributes(attributes)
|
73
|
-
self.save
|
74
|
-
end
|
75
|
-
|
76
32
|
def create_or_update
|
77
33
|
# since the same model can be created or updated twice from a relationship we have to have this guard
|
78
34
|
@_create_or_updating = true
|
@@ -145,6 +101,7 @@ module Neo4j::Shared
|
|
145
101
|
|
146
102
|
def reload
|
147
103
|
return self if new_record?
|
104
|
+
clear_association_cache
|
148
105
|
changed_attributes && changed_attributes.clear
|
149
106
|
unless reload_from_database
|
150
107
|
@_deleted = true
|
@@ -164,30 +121,34 @@ module Neo4j::Shared
|
|
164
121
|
# Updates this resource with all the attributes from the passed-in Hash and requests that the record be saved.
|
165
122
|
# If saving fails because the resource is invalid then false will be returned.
|
166
123
|
def update(attributes)
|
167
|
-
self.attributes = attributes
|
124
|
+
self.attributes = process_attributes(attributes)
|
168
125
|
save
|
169
126
|
end
|
170
127
|
alias_method :update_attributes, :update
|
171
128
|
|
172
129
|
# Same as {#update_attributes}, but raises an exception if saving fails.
|
173
130
|
def update!(attributes)
|
174
|
-
self.attributes = attributes
|
131
|
+
self.attributes = process_attributes(attributes)
|
175
132
|
save!
|
176
133
|
end
|
177
134
|
alias_method :update_attributes!, :update!
|
178
135
|
|
179
136
|
def cache_key
|
180
137
|
if self.new_record?
|
181
|
-
"#{
|
138
|
+
"#{model_cache_key}/new"
|
182
139
|
elsif self.respond_to?(:updated_at) && !self.updated_at.blank?
|
183
|
-
"#{
|
140
|
+
"#{model_cache_key}/#{neo_id}-#{self.updated_at.utc.to_s(:number)}"
|
184
141
|
else
|
185
|
-
"#{
|
142
|
+
"#{model_cache_key}/#{neo_id}"
|
186
143
|
end
|
187
144
|
end
|
188
145
|
|
189
146
|
private
|
190
147
|
|
148
|
+
def model_cache_key
|
149
|
+
self.class.model_name.cache_key
|
150
|
+
end
|
151
|
+
|
191
152
|
def create_magic_properties
|
192
153
|
end
|
193
154
|
|
@@ -199,16 +160,9 @@ module Neo4j::Shared
|
|
199
160
|
props[:_classname] = self.class.name if self.class.cached_class?
|
200
161
|
end
|
201
162
|
|
202
|
-
# def assign_attributes(attributes)
|
203
|
-
# attributes.each do |attribute, value|
|
204
|
-
# send("#{attribute}=", value)
|
205
|
-
# end
|
206
|
-
# end
|
207
|
-
|
208
163
|
def set_timestamps
|
209
164
|
self.created_at = DateTime.now if respond_to?(:created_at=)
|
210
165
|
self.updated_at = self.created_at if respond_to?(:updated_at=)
|
211
166
|
end
|
212
|
-
|
213
167
|
end
|
214
168
|
end
|