rails_age 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,75 +0,0 @@
1
- module ApacheAge
2
- module ClassMethods
3
- # for now we only allow one predertimed graph
4
- def create(attributes) = new(**attributes).save
5
-
6
- def find_by(attributes)
7
- where_clause = attributes.map { |k, v| "find.#{k} = '#{v}'" }.join(' AND ')
8
- cypher_sql = find_sql(where_clause)
9
- execute_find(cypher_sql)
10
- end
11
-
12
- def find(id)
13
- where_clause = "id(find) = #{id}"
14
- cypher_sql = find_sql(where_clause)
15
- execute_find(cypher_sql)
16
- end
17
-
18
- def all
19
- age_results = ActiveRecord::Base.connection.execute(all_sql)
20
- return [] if age_results.values.count.zero?
21
-
22
- age_results.values.map do |result|
23
- json_string = result.first.split('::').first
24
- hash = JSON.parse(json_string)
25
- attribs = hash.except('label', 'properties').merge(hash['properties']).symbolize_keys
26
-
27
- new(**attribs)
28
- end
29
- end
30
-
31
- # Private stuff
32
-
33
- def age_graph = 'age_schema'
34
- def age_label = name.gsub('::', '__')
35
- def age_type = name.constantize.new.age_type
36
-
37
- def match_clause
38
- age_type == 'vertex' ? "(find:#{age_label})" : "()-[find:#{age_label}]->()"
39
- end
40
-
41
- def execute_find(cypher_sql)
42
- age_result = ActiveRecord::Base.connection.execute(cypher_sql)
43
- return nil if age_result.values.count.zero?
44
-
45
- age_type = age_result.values.first.first.split('::').last
46
- json_data = age_result.values.first.first.split('::').first
47
-
48
- hash = JSON.parse(json_data)
49
- attribs = hash.except('label', 'properties').merge(hash['properties']).symbolize_keys
50
-
51
- new(**attribs)
52
- end
53
-
54
- def all_sql
55
- <<-SQL
56
- SELECT *
57
- FROM cypher('#{age_graph}', $$
58
- MATCH #{match_clause}
59
- RETURN find
60
- $$) as (#{age_label} agtype);
61
- SQL
62
- end
63
-
64
- def find_sql(where_clause)
65
- <<-SQL
66
- SELECT *
67
- FROM cypher('#{age_graph}', $$
68
- MATCH #{match_clause}
69
- WHERE #{where_clause}
70
- RETURN find
71
- $$) as (#{age_label} agtype);
72
- SQL
73
- end
74
- end
75
- end
@@ -1,126 +0,0 @@
1
- module ApacheAge
2
- module CommonMethods
3
- def initialize(**attributes)
4
- super
5
- return self unless age_type == 'edge'
6
-
7
- self.end_id ||= end_node.id if end_node
8
- self.start_id ||= start_node.id if start_node
9
- self.end_node ||= Entity.find(end_id) if end_id
10
- self.start_node ||= Entity.find(start_id) if start_id
11
- end
12
-
13
- # for now we just can just use one schema
14
- def age_graph = 'age_schema'
15
- def age_label = self.class.name.gsub('::', '__')
16
- def persisted? = id.present?
17
- def to_s = ":#{age_label} #{properties_to_s}"
18
-
19
- def to_h
20
- base_h = attributes.to_hash
21
- if age_type == 'edge'
22
- # remove the nodes (in attribute form and re-add in hash form)
23
- base_h = base_h.except('start_node', 'end_node')
24
- base_h[:end_node] = end_node.to_h if end_node
25
- base_h[:start_node] = start_node.to_h if start_node
26
- end
27
- base_h.symbolize_keys
28
- end
29
-
30
- def update_attributes(attribs)
31
- attribs.except(id:).each do |key, value|
32
- send("#{key}=", value) if respond_to?("#{key}=")
33
- end
34
- end
35
-
36
- def update(attribs)
37
- update_attributes(attribs)
38
- save
39
- end
40
-
41
- def save
42
- return false unless valid?
43
-
44
- cypher_sql = (persisted? ? update_sql : create_sql)
45
- response_hash = execute_sql(cypher_sql)
46
-
47
- self.id = response_hash['id']
48
-
49
- if age_type == 'edge'
50
- self.end_id = response_hash['end_id']
51
- self.start_id = response_hash['start_id']
52
- # reload the nodes? (can we change the nodes?)
53
- # self.end_node = ApacheAge::Entity.find(end_id)
54
- # self.start_node = ApacheAge::Entity.find(start_id)
55
- end
56
-
57
- self
58
- end
59
-
60
- def destroy
61
- match_clause = (age_type == 'vertex' ? "(done:#{age_label})" : "()-[done:#{age_label}]->()")
62
- delete_clause = (age_type == 'vertex' ? 'DETACH DELETE done' : 'DELETE done')
63
- cypher_sql =
64
- <<-SQL
65
- SELECT *
66
- FROM cypher('#{age_graph}', $$
67
- MATCH #{match_clause}
68
- WHERE id(done) = #{id}
69
- #{delete_clause}
70
- return done
71
- $$) as (deleted agtype);
72
- SQL
73
-
74
- hash = execute_sql(cypher_sql)
75
- return nil if hash.blank?
76
-
77
- self.id = nil
78
- self
79
- end
80
- alias destroy! destroy
81
- alias delete destroy
82
-
83
- # private
84
-
85
- def age_properties
86
- attrs = attributes.except('id')
87
- attrs = attrs.except('end_node', 'start_node', 'end_id', 'start_id') if age_type == 'edge'
88
- attrs.symbolize_keys
89
- end
90
-
91
- def age_hash
92
- hash =
93
- {
94
- id:,
95
- label: age_label,
96
- properties: age_properties
97
- }
98
- hash.merge!(end_id:, start_id:) if age_type == 'edge'
99
- hash.transform_keys(&:to_s)
100
- end
101
-
102
- def properties_to_s
103
- string_values =
104
- age_properties.each_with_object([]) do |(key, val), array|
105
- array << "#{key}: '#{val}'"
106
- end
107
- "{#{string_values.join(', ')}}"
108
- end
109
-
110
- def age_alias
111
- return nil if id.blank?
112
-
113
- # we start the alias with a since we can't start with a number
114
- 'a' + Digest::SHA256.hexdigest(id.to_s).to_i(16).to_s(36)[0..9]
115
- end
116
-
117
- def execute_sql(cypher_sql)
118
- age_result = ActiveRecord::Base.connection.execute(cypher_sql)
119
- age_type = age_result.values.first.first.split('::').last
120
- json_data = age_result.values.first.first.split('::').first
121
- # json_data = age_result.to_a.first.values.first.split("::#{age_type}").first
122
-
123
- JSON.parse(json_data)
124
- end
125
- end
126
- end
@@ -1,64 +0,0 @@
1
- module ApacheAge
2
- module Edge
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- include ActiveModel::Model
7
- include ActiveModel::Dirty
8
- include ActiveModel::Attributes
9
-
10
- attribute :id, :integer
11
- attribute :end_id, :integer
12
- attribute :start_id, :integer
13
- attribute :end_node # :vertex
14
- attribute :start_node # :vertex
15
-
16
- validates :end_node, :start_node, presence: true
17
-
18
- extend ApacheAge::ClassMethods
19
- include ApacheAge::CommonMethods
20
- end
21
-
22
- def age_type = 'edge'
23
-
24
- # AgeSchema::Edges::WorksAt.create(
25
- # start_node: fred, end_node: quarry, employee_role: 'Crane Operator'
26
- # )
27
- # SELECT *
28
- # FROM cypher('age_schema', $$
29
- # MATCH (start_vertex:Person), (end_vertex:Company)
30
- # WHERE id(start_vertex) = 1125899906842634 and id(end_vertex) = 844424930131976
31
- # CREATE (start_vertex)-[edge:WorksAt {employee_role: 'Crane Operator'}]->(end_vertex)
32
- # RETURN edge
33
- # $$) as (edge agtype);
34
- def create_sql
35
- self.start_node = start_node.save unless start_node.persisted?
36
- self.end_node = end_node.save unless end_node.persisted?
37
- <<-SQL
38
- SELECT *
39
- FROM cypher('#{age_graph}', $$
40
- MATCH (from_node:#{start_node.age_label}), (to_node:#{end_node.age_label})
41
- WHERE id(from_node) = #{start_node.id} and id(to_node) = #{end_node.id}
42
- CREATE (from_node)-[edge#{self}]->(to_node)
43
- RETURN edge
44
- $$) as (edge agtype);
45
- SQL
46
- end
47
-
48
- # So far just properties of string type with '' around them
49
- def update_sql
50
- alias_name = age_alias || age_label.downcase
51
- set_caluse =
52
- age_properties.map { |k, v| v ? "#{alias_name}.#{k} = '#{v}'" : "#{alias_name}.#{k} = NULL" }.join(', ')
53
- <<-SQL
54
- SELECT *
55
- FROM cypher('#{age_graph}', $$
56
- MATCH ()-[#{alias_name}:#{age_label}]->()
57
- WHERE id(#{alias_name}) = #{id}
58
- SET #{set_caluse}
59
- RETURN #{alias_name}
60
- $$) as (#{age_label} agtype);
61
- SQL
62
- end
63
- end
64
- end
@@ -1,67 +0,0 @@
1
- module ApacheAge
2
- class Entity
3
- class << self
4
- def find_by(attributes)
5
- where_clause = attributes.map { |k, v| "find.#{k} = '#{v}'" }.join(' AND ')
6
- handle_find(where_clause)
7
- end
8
-
9
- def find(id)
10
- where_clause = "id(find) = #{id}"
11
- handle_find(where_clause)
12
- end
13
-
14
- private
15
-
16
- def age_graph = 'age_schema'
17
-
18
- def handle_find(where_clause)
19
- # try to find a vertex
20
- match_node = '(find)'
21
- cypher_sql = find_sql(match_node, where_clause)
22
- age_response = execute_find(cypher_sql)
23
-
24
- if age_response.nil?
25
- # if not a vertex try to find an edge
26
- match_edge = '()-[find]->()'
27
- cypher_sql = find_sql(match_edge, where_clause)
28
- age_response = execute_find(cypher_sql)
29
- return nil if age_response.nil?
30
- end
31
-
32
- instantiate_result(age_response)
33
- end
34
-
35
- def execute_find(cypher_sql)
36
- age_result = ActiveRecord::Base.connection.execute(cypher_sql)
37
- return nil if age_result.values.first.nil?
38
-
39
- age_result
40
- end
41
-
42
- def instantiate_result(age_response)
43
- age_type = age_response.values.first.first.split('::').last
44
- json_string = age_response.values.first.first.split('::').first
45
- json_data = JSON.parse(json_string)
46
-
47
- age_label = json_data['label']
48
- attribs = json_data.except('label', 'properties')
49
- .merge(json_data['properties'])
50
- .symbolize_keys
51
-
52
- "#{json_data['label'].gsub('__', '::')}".constantize.new(**attribs)
53
- end
54
-
55
- def find_sql(match_clause, where_clause)
56
- <<-SQL
57
- SELECT *
58
- FROM cypher('#{age_graph}', $$
59
- MATCH #{match_clause}
60
- WHERE #{where_clause}
61
- RETURN find
62
- $$) as (found agtype);
63
- SQL
64
- end
65
- end
66
- end
67
- end
@@ -1,52 +0,0 @@
1
- module ApacheAge
2
- module Vertex
3
- extend ActiveSupport::Concern
4
- # include ApacheAge::Entity
5
-
6
- included do
7
- include ActiveModel::Model
8
- include ActiveModel::Dirty
9
- include ActiveModel::Attributes
10
-
11
- attribute :id, :integer
12
-
13
- extend ApacheAge::ClassMethods
14
- include ApacheAge::CommonMethods
15
- end
16
-
17
- def age_type = 'vertex'
18
-
19
- # AgeSchema::Nodes::Company.create(company_name: 'Bedrock Quarry')
20
- # SELECT *
21
- # FROM cypher('age_schema', $$
22
- # CREATE (company:Company {company_name: 'Bedrock Quarry'})
23
- # RETURN company
24
- # $$) as (Company agtype);
25
- def create_sql
26
- alias_name = age_alias || age_label.downcase
27
- <<-SQL
28
- SELECT *
29
- FROM cypher('#{age_graph}', $$
30
- CREATE (#{alias_name}#{self})
31
- RETURN #{alias_name}
32
- $$) as (#{age_label} agtype);
33
- SQL
34
- end
35
-
36
- # So far just properties of string type with '' around them
37
- def update_sql
38
- alias_name = age_alias || age_label.downcase
39
- set_caluse =
40
- age_properties.map { |k, v| v ? "#{alias_name}.#{k} = '#{v}'" : "#{alias_name}.#{k} = NULL" }.join(', ')
41
- <<-SQL
42
- SELECT *
43
- FROM cypher('#{age_graph}', $$
44
- MATCH (#{alias_name}:#{age_label})
45
- WHERE id(#{alias_name}) = #{id}
46
- SET #{set_caluse}
47
- RETURN #{alias_name}
48
- $$) as (#{age_label} agtype);
49
- SQL
50
- end
51
- end
52
- end