rails_age 0.1.0 → 0.3.0

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.
@@ -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