cancancan-neo4j 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f5213aae2b6c9b1dced0d36464e2ae1c458f9fc9
4
- data.tar.gz: dcddcb66fef4186dc1a8ac08c4e11619982d645a
2
+ SHA256:
3
+ metadata.gz: 80f5ce945f4e2b8449a73be0c5d203c47899f2ce2d0332bfb9db82bff568e4c1
4
+ data.tar.gz: 9ac02736ba3b4ae898f67c954c45dac7059d9e4c867795699b1bc64a7036d965
5
5
  SHA512:
6
- metadata.gz: '008f34d8928100cb0d40cd291f30567238007cdf3a3358766d6f2990244caf6bb76e9296ac35a5989f0a09830923c94e67d5dfb6e9f3a4e0e304cb4dcfb9c725'
7
- data.tar.gz: 1a7a2ceff81a4038556862cff6281a05987286732395c4792701b53c23b2c8fb0452aa185d7d2635a8ee5d0b326077b773897108763dbccf61e6d0dc76a41571
6
+ metadata.gz: f1f6de129648660e99814b2e3a2869f35d62d105879bc2d2b4e75e58c9e1a4ed0db2a15a688df731c11717dbef9db1ae1ee984a3c3d6c5155b0655b13d533c46
7
+ data.tar.gz: 26393b95bc052363bbc607e05ad740dead1bc8fc7829dd2705bdddcd21d491ae160084489b56c6520230d77ff5a26b8932dc95b4d63a6781d4c319d5da138b96
@@ -18,8 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.files = `git ls-files lib init.rb cancancan-neo4j.gemspec`.split($INPUT_RECORD_SEPARATOR)
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency 'activemodel', '<5.2.0'
22
- spec.add_dependency 'cancancan', '<=2.1.4'
21
+ spec.add_dependency 'cancancan'
23
22
  spec.add_dependency 'neo4j', '>= 9.0.0'
24
23
 
25
24
  spec.add_development_dependency 'bundler', '>= 1.3'
@@ -1,5 +1,6 @@
1
1
  require 'cancancan/neo4j/cypher_constructor_helper'
2
2
  require 'cancancan/neo4j/rule_cypher'
3
+ require 'cancancan/neo4j/cypher_constructor'
3
4
 
4
5
  module CanCan
5
6
  module ModelAdapters
@@ -26,99 +27,69 @@ module CanCan
26
27
  end
27
28
 
28
29
  def self.all_conditions_match?(subject, conditions, base_class)
29
- asso_conditions, model_conditions = CanCanCan::Neo4j::CypherConstructorHelper
30
- .bifurcate_conditions(conditions)
31
- associations_conditions_match?(asso_conditions, subject, base_class) &&
32
- model_conditions_matches?(model_conditions, subject, base_class)
33
- end
34
-
35
- def self.model_conditions_matches?(conditions, subject, base_class)
36
- return true if conditions.blank?
37
- conditions = conditions.partition do |key, _|
38
- base_class.associations_keys.include?(key)
39
- end
40
- associations_conditions, atrribute_conditions = conditions.map(&:to_h)
41
- matches_attribute_conditions?(atrribute_conditions, subject) &&
42
- matches_associations_relations(associations_conditions, subject)
43
- end
44
-
45
- # checks if associations exists on given node
46
- def self.matches_associations_relations(conditions, subject)
47
- return true if conditions.blank?
48
- conditions.all? do |association, value|
49
- association_exists = subject.send(association).exists?
50
- value ? association_exists : !association_exists
30
+ return false unless subject
31
+ conditions.all? do |key, value|
32
+ if (relation = base_class.associations[key])
33
+ match_relation_conditions(value, subject, relation)
34
+ else
35
+ property_matches?(subject, key, value)
36
+ end
51
37
  end
52
38
  end
53
39
 
54
- def self.matches_attribute_conditions?(conditions, subject)
55
- return true if conditions.blank?
40
+ def self.property_matches?(subject, property, value)
56
41
  if subject.is_a?(Neo4j::ActiveNode::HasN::AssociationProxy)
57
- subject.where(conditions).exists?
42
+ subject.where(property => value).exists?
58
43
  else
59
- conditions.all? do |attribute, value|
60
- subject.send(attribute) == value
61
- end
44
+ subject.send(property) == value
62
45
  end
63
46
  end
64
47
 
65
- def self.associations_conditions_match?(conditions, subject, base_class)
66
- return true if conditions.blank?
67
- conditions.all? do |association, conditions_hash|
68
- rel_length = conditions_hash.delete(:rel_length)
69
- current_subject = subject.send(association, rel_length: rel_length)
70
- return false unless current_subject
71
- current_model = base_class.associations[association].target_class
72
- all_conditions_match?(current_subject, conditions_hash, current_model)
73
- end
48
+ def self.match_relation_conditions(conditions, subject, association)
49
+ rel_length = conditions.delete(:rel_length) if conditions.is_a?(Hash)
50
+ subject = subject.send(association.name, rel_length: rel_length)
51
+ return !subject.exists? if conditions.blank?
52
+ return subject.exists? if conditions == true
53
+ all_conditions_match?(subject, conditions, association.target_class)
74
54
  end
75
55
 
76
56
  private
77
57
 
78
58
  def records_for_multiple_rules
79
- base_query = base_query_proxy.query
80
- cypher_options = construct_cypher_options
81
- cypher_options[:matches].reject! { |mt| mt.match(var_name(@model_class)) }
82
- match_string = cypher_options[:matches].uniq.join(', ')
83
- base_query = base_query.match(match_string) unless match_string.blank?
84
- base_query
85
- .proxy_as(@model_class, var_name(@model_class))
86
- .where(cypher_options[:conditions])
59
+ CanCanCan::Neo4j::CypherConstructor
60
+ .new(construct_cypher_options)
61
+ .query
62
+ .proxy_as(@model_class, var_name)
87
63
  end
88
64
 
89
65
  def construct_cypher_options
90
- default_options = { conditions: '', matches: [] }
91
- @rules.reverse.each_with_object(default_options) do |rule, options|
92
- rule_options = { rule: rule, model_class: @model_class }
93
- rule_cypher = CanCanCan::Neo4j::RuleCypher.new(rule_options)
94
- CanCanCan::Neo4j::CypherConstructorHelper
95
- .append_and_or_to_conditions(options, rule_cypher)
96
- options[:conditions] += ('(' + rule_cypher.rule_conditions + ')')
97
- options[:matches] += rule_cypher.cypher_matches
98
- options
66
+ @rules.reverse.collect.with_index do |rule, index|
67
+ opts = { rule: rule, model_class: @model_class, index: index }
68
+ CanCanCan::Neo4j::RuleCypher.new(opts)
99
69
  end
100
70
  end
101
71
 
102
- def base_query_proxy
103
- @model_class.as(var_name(@model_class))
104
- end
105
-
106
72
  def override_scope
107
73
  conditions = @rules.map(&:conditions).compact
108
- return unless conditions.any? { |condition| condition.is_a?(Neo4j::ActiveNode::Query::QueryProxy) }
74
+ return unless conditions.any? do |condition|
75
+ condition.is_a?(Neo4j::ActiveNode::Query::QueryProxy)
76
+ end
109
77
  return conditions.first if conditions.size == 1
110
78
  raise_override_scope_error
111
79
  end
112
80
 
113
81
  def raise_override_scope_error
114
- rule_found = @rules.detect { |rule| rule.conditions.is_a?(Neo4j::ActiveNode::Query::QueryProxy) }
82
+ rule_found = @rules.detect do |rule|
83
+ rule.conditions.is_a?(Neo4j::ActiveNode::Query::QueryProxy)
84
+ end
115
85
  raise Error,
116
86
  'Unable to merge an ActiveNode scope with other conditions. '\
117
- "Instead use a hash for #{rule_found.actions.first} #{rule_found.subjects.first} ability."
87
+ "Instead use a hash for #{rule_found.actions.first}"\
88
+ " #{rule_found.subjects.first} ability."
118
89
  end
119
90
 
120
- def var_name(model_class)
121
- CanCanCan::Neo4j::CypherConstructorHelper.var_name(model_class)
91
+ def var_name
92
+ CanCanCan::Neo4j::CypherConstructorHelper.var_name(@model_class)
122
93
  end
123
94
  end
124
95
  end
@@ -1,3 +1,4 @@
1
+ require 'active_support'
1
2
  require 'cancancan'
2
3
  require 'neo4j'
3
4
 
@@ -0,0 +1,83 @@
1
+ require 'cancancan/neo4j/cypher_constructor_helper'
2
+
3
+ module CanCanCan
4
+ module Neo4j
5
+ # Constructs cypher query from rule cypher options
6
+ class CypherConstructor
7
+ attr_reader :query
8
+
9
+ def initialize(rule_cyphers)
10
+ @model_class = rule_cyphers.first.options[:model_class]
11
+ reset_variables
12
+ construct_cypher(rule_cyphers)
13
+ end
14
+
15
+ def reset_variables
16
+ @query = @model_class.new_query
17
+ @current_collection = nil
18
+ end
19
+
20
+ def construct_cypher(rule_cyphers)
21
+ rule_cyphers.each do |rule_cypher|
22
+ rule = rule_cypher.options[:rule]
23
+ reset_variables if rule.conditions.blank?
24
+ if rule.base_behavior
25
+ construct_can_cypher(rule_cypher)
26
+ else
27
+ construct_cannot_cypher(rule_cypher)
28
+ end
29
+ end
30
+ unwind_query_with_distinct
31
+ end
32
+
33
+ def unwind_query_with_distinct
34
+ var = CanCanCan::Neo4j::CypherConstructorHelper.var_name(@model_class)
35
+ @query = unwind_qeury("#{var}_can")
36
+ .with("DISTINCT #{var}_can as #{var}")
37
+ end
38
+
39
+ def unwind_qeury(var_name)
40
+ @query = @query.unwind("#{@current_collection} as #{var_name}")
41
+ end
42
+
43
+ def construct_can_cypher(rule_cypher)
44
+ with_clause = with_clause_for_rule(rule_cypher, true)
45
+ @query = @query.optional_match(rule_cypher.path)
46
+ .where(rule_cypher.rule_conditions)
47
+ .with(with_clause)
48
+ end
49
+
50
+ def with_clause_for_rule(rule_cypher, can_rule)
51
+ var = rule_cypher.options[:var_label]
52
+ with = "collect(DISTINCT #{var}) as #{var}_col"
53
+ if can_rule && @current_collection
54
+ with = "#{@current_collection} + #{with}"
55
+ end
56
+ @current_collection = "#{var}_col"
57
+ with
58
+ end
59
+
60
+ def construct_cannot_cypher(rule_cypher)
61
+ match_cls = match_clause(rule_cypher)
62
+ unwind_for_cannot(rule_cypher)
63
+ @query = @query.break
64
+ .match(match_cls)
65
+ .where_not(rule_cypher.rule_conditions)
66
+ with_claus = with_clause_for_rule(rule_cypher, false)
67
+ @query = @query.with(with_claus)
68
+ end
69
+
70
+ def unwind_for_cannot(rule_cypher)
71
+ return unless @current_collection.present?
72
+ var = rule_cypher.options[:var_label]
73
+ @query = unwind_qeury(var)
74
+ .with("DISTINCT #{var} as #{var}")
75
+ end
76
+
77
+ def match_clause(rule_cypher)
78
+ var = rule_cypher.options[:var_label]
79
+ @current_collection.present? ? "(#{var})" : rule_cypher.path
80
+ end
81
+ end
82
+ end
83
+ end
@@ -3,72 +3,30 @@ module CanCanCan
3
3
  # Cypher query constructs
4
4
  class CypherConstructorHelper
5
5
  class << self
6
- def match_node_cypher(node_class)
7
- "(#{var_name(node_class)}:`#{node_class.mapped_label_name}`)"
8
- end
9
-
10
- def construct_conditions_string(conditions_hash, base_class, path = '')
11
- variable_name = var_name(base_class)
12
- conditions_hash.collect do |key, value|
13
- condition = if base_class.associations_keys.include?(key)
14
- con = condtion_for_path(path: path,
15
- variable_name: variable_name,
16
- base_class: base_class,
17
- key: key)
18
- value ? con : ' NOT ' + con
19
- elsif key == :id
20
- condition_for_id(base_class, variable_name, value)
21
- else
22
- condition_for_attribute(value, variable_name, key)
23
- end
24
- '(' + condition + ')'
25
- end.join(' AND ')
26
- end
27
-
28
- def condition_for_attribute(value, variable_name, attribute)
29
- lhs = variable_name + '.' + attribute.to_s
30
- return lhs + ' IS NULL ' if value.nil?
31
- rhs = value.to_s
32
- rhs = "'" + rhs + "'" unless [true, false].include?(value)
33
- lhs + '=' + rhs
34
- end
35
-
36
- def condtion_for_path(path:, variable_name:, base_class:, key:)
37
- path = "(#{variable_name})" if path.blank?
38
- relationship = base_class.associations[key]
39
- path + relationship.arrow_cypher + path_end_node(relationship)
40
- end
41
-
42
- def condition_for_id(base_class, variable_name, value)
43
- id_property = base_class.id_property_name
44
- if id_property == :neo_id
45
- "ID(#{variable_name})=#{value}"
46
- else
47
- variable_name + '.' + id_property.to_s + '=' + "'#{value}'"
48
- end
49
- end
50
-
51
6
  def var_name(class_constant)
52
7
  class_constant.name.downcase.split('::').join('_')
53
8
  end
54
9
 
55
- def bifurcate_conditions(conditions)
56
- conditions.partition { |_, value| value.is_a?(Hash) }.map(&:to_h)
10
+ def path_node(target_class, var_label)
11
+ label = target_class.mapped_label_names
12
+ .map { |label_name| ":`#{label_name}`" }
13
+ .join
14
+ "(#{var_label}#{label})"
57
15
  end
58
16
 
59
- def append_and_or_to_conditions(cypher_options, rule_cypher)
60
- conditions_string = cypher_options[:conditions]
61
- connector = if conditions_string.blank?
62
- ''
63
- else
64
- rule_cypher.conditions_connector
65
- end
66
- connector += 'NOT' if rule_cypher.append_not_to_conditions?
67
- cypher_options[:conditions] = conditions_string + connector
17
+ def variable_in_path?(relationship, conditions)
18
+ boolean = [TrueClass, FalseClass].include?(conditions.class)
19
+ return false if conditions.blank? || boolean
20
+ !relationship.target_class
21
+ .associations[conditions.keys.first]
22
+ .present?
68
23
  end
69
24
 
70
- def path_end_node(relationship)
71
- '(' + relationship.target_class.mapped_label_names.map { |label_name| ":`#{label_name}`" }.join + ')'
25
+ def path_end_node(relationship, conditions)
26
+ with_var = variable_in_path?(relationship, conditions)
27
+ target_class = relationship.target_class
28
+ var_label = with_var ? var_name(target_class) : ''
29
+ path_node(target_class, var_label)
72
30
  end
73
31
  end
74
32
  end
@@ -1,35 +1,34 @@
1
1
  require 'cancancan/neo4j/cypher_constructor_helper'
2
- require 'cancancan/neo4j/association_conditions'
3
2
 
4
3
  module CanCanCan
5
4
  module Neo4j
6
5
  # Constructs cypher conditions for rule and cypher match classes
7
6
  class RuleCypher
8
- attr_reader :rule_conditions, :cypher_matches
7
+ attr_reader :rule_conditions, :path, :options
9
8
 
10
9
  def initialize(options)
11
10
  @options = options
12
- @rule_conditions = ''
13
- @cypher_matches = []
11
+ @rule_conditions = {}
12
+ initialize_path
14
13
  construct_cypher_conditions
15
14
  end
16
15
 
16
+ def initialize_path
17
+ model_class = @options[:model_class]
18
+ var_label = CypherConstructorHelper.var_name(model_class)
19
+ var_label += ('_' + (@options[:index] + 1).to_s)
20
+ @options[:var_label] = var_label
21
+ @path = CypherConstructorHelper.path_node(model_class, var_label)
22
+ end
23
+
17
24
  def construct_cypher_conditions
18
25
  if @options[:rule].conditions.blank?
19
26
  condition_for_rule_without_conditions
20
27
  else
21
- set_cypher_options
28
+ construct_cypher_options
22
29
  end
23
30
  end
24
31
 
25
- def conditions_connector
26
- @options[:rule].base_behavior ? ' OR ' : ' AND '
27
- end
28
-
29
- def append_not_to_conditions?
30
- !rule_conditions_blank? && !@options[:rule].base_behavior
31
- end
32
-
33
32
  private
34
33
 
35
34
  def rule_conditions_blank?
@@ -40,23 +39,65 @@ module CanCanCan
40
39
  @rule_conditions = @options[:rule].base_behavior ? '(true)' : '(false)'
41
40
  end
42
41
 
43
- def set_cypher_options
44
- associations_conditions, model_conditions = CypherConstructorHelper.bifurcate_conditions(@options[:rule].conditions)
45
- @rule_conditions = CypherConstructorHelper.construct_conditions_string(model_conditions, @options[:model_class], default_path) unless model_conditions.blank?
46
- return if associations_conditions.blank?
47
- append_association_conditions(associations_conditions)
42
+ def construct_cypher_options
43
+ @options[:rule].conditions.deep_dup.each do |key, conditions|
44
+ hash_cypher_options(key, conditions, @options[:model_class])
45
+ end
48
46
  end
49
47
 
50
- def append_association_conditions(conditions_hash)
51
- options = { asso_conditions: conditions_hash, parent_class: @options[:model_class], path: default_path }
52
- asso_conditions_obj = AssociationConditions.new(options)
53
- @rule_conditions += ' AND ' unless @rule_conditions.blank?
54
- @rule_conditions += asso_conditions_obj.conditions_string
55
- @cypher_matches += asso_conditions_obj.cypher_matches
48
+ def hash_cypher_options(key, conditions, base_class)
49
+ if (rel = base_class.associations[key])
50
+ update_path_with_rel(conditions, rel)
51
+ cypher_for_relation_conditions(conditions, rel)
52
+ else
53
+ merge_conditions(key, conditions, base_class)
54
+ end
55
+ end
56
+
57
+ def update_path_with_rel(conditions, rel)
58
+ rel_length = conditions.delete(:rel_length) if conditions
59
+ arrow_cypher = rel.arrow_cypher(nil, {}, false, false, rel_length)
60
+ node_label = CypherConstructorHelper.path_end_node(rel, conditions)
61
+ @path += (arrow_cypher + node_label)
56
62
  end
57
63
 
58
- def default_path
59
- CypherConstructorHelper.match_node_cypher(@options[:model_class])
64
+ def cypher_for_relation_conditions(conditions, relationship)
65
+ if conditions.is_a?(Hash)
66
+ conditions.each do |key, con|
67
+ hash_cypher_options(key, con, relationship.target_class)
68
+ end
69
+ else
70
+ update_conditions_with_path(conditions ? '' : 'NOT ')
71
+ end
72
+ end
73
+
74
+ def update_conditions_with_path(not_str)
75
+ @rule_conditions = not_str + @path
76
+ initialize_path
77
+ end
78
+
79
+ def merge_conditions(key, value, base_class)
80
+ var_name = var_label_for_conditions(base_class, key)
81
+ if key == :id
82
+ merge_condition_for_id(var_name, base_class, value)
83
+ else
84
+ (@rule_conditions[var_name] ||= {}).merge!(key => value)
85
+ end
86
+ end
87
+
88
+ def var_label_for_conditions(base_class, key)
89
+ condition_keys = @options[:rule].conditions.keys
90
+ return @options[:var_label] if condition_keys.include?(key)
91
+ CypherConstructorHelper.var_name(base_class)
92
+ end
93
+
94
+ def merge_condition_for_id(var_name, base_class, value)
95
+ id_property_name = base_class.id_property_name
96
+ if id_property_name == :neo_id
97
+ @rule_conditions.merge!("ID(#{var_name})" => value)
98
+ else
99
+ (@rule_conditions[var_name] ||= {}).merge!(id_property_name => value)
100
+ end
60
101
  end
61
102
  end
62
103
  end
@@ -2,6 +2,6 @@ module CanCanCan
2
2
  end
3
3
  module CanCanCan
4
4
  module Neo4j
5
- VERSION = '1.2.2'.freeze
5
+ VERSION = '1.3.0'.freeze
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,150 +1,122 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cancancan-neo4j
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amit Suryavanshi
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-01 00:00:00.000000000 Z
11
+ date: 2018-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
+ name: cancancan
14
15
  requirement: !ruby/object:Gem::Requirement
15
16
  requirements:
16
- - - "<"
17
+ - - ">="
17
18
  - !ruby/object:Gem::Version
18
- version: 5.2.0
19
- name: activemodel
20
- prerelease: false
19
+ version: '0'
21
20
  type: :runtime
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "<"
25
- - !ruby/object:Gem::Version
26
- version: 5.2.0
27
- - !ruby/object:Gem::Dependency
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - "<="
31
- - !ruby/object:Gem::Version
32
- version: 2.1.4
33
- name: cancancan
34
21
  prerelease: false
35
- type: :runtime
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
- - - "<="
24
+ - - ">="
39
25
  - !ruby/object:Gem::Version
40
- version: 2.1.4
26
+ version: '0'
41
27
  - !ruby/object:Gem::Dependency
28
+ name: neo4j
42
29
  requirement: !ruby/object:Gem::Requirement
43
30
  requirements:
44
31
  - - ">="
45
32
  - !ruby/object:Gem::Version
46
33
  version: 9.0.0
47
- name: neo4j
48
- prerelease: false
49
34
  type: :runtime
35
+ prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
38
  - - ">="
53
39
  - !ruby/object:Gem::Version
54
40
  version: 9.0.0
55
41
  - !ruby/object:Gem::Dependency
42
+ name: bundler
56
43
  requirement: !ruby/object:Gem::Requirement
57
44
  requirements:
58
45
  - - ">="
59
46
  - !ruby/object:Gem::Version
60
47
  version: '1.3'
61
- name: bundler
62
- prerelease: false
63
48
  type: :development
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '1.3'
69
- - !ruby/object:Gem::Dependency
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '0'
75
- name: neo4j-community
76
49
  prerelease: false
77
- type: :development
78
50
  version_requirements: !ruby/object:Gem::Requirement
79
51
  requirements:
80
52
  - - ">="
81
53
  - !ruby/object:Gem::Version
82
- version: '0'
54
+ version: '1.3'
83
55
  - !ruby/object:Gem::Dependency
56
+ name: neo4j-rake_tasks
84
57
  requirement: !ruby/object:Gem::Requirement
85
58
  requirements:
86
59
  - - ">="
87
60
  - !ruby/object:Gem::Version
88
61
  version: 0.3.0
89
- name: neo4j-rake_tasks
90
- prerelease: false
91
62
  type: :development
63
+ prerelease: false
92
64
  version_requirements: !ruby/object:Gem::Requirement
93
65
  requirements:
94
66
  - - ">="
95
67
  - !ruby/object:Gem::Version
96
68
  version: 0.3.0
97
69
  - !ruby/object:Gem::Dependency
70
+ name: pry
98
71
  requirement: !ruby/object:Gem::Requirement
99
72
  requirements:
100
73
  - - ">="
101
74
  - !ruby/object:Gem::Version
102
75
  version: 0.11.3
103
- name: pry
104
- prerelease: false
105
76
  type: :development
77
+ prerelease: false
106
78
  version_requirements: !ruby/object:Gem::Requirement
107
79
  requirements:
108
80
  - - ">="
109
81
  - !ruby/object:Gem::Version
110
82
  version: 0.11.3
111
83
  - !ruby/object:Gem::Dependency
84
+ name: rake
112
85
  requirement: !ruby/object:Gem::Requirement
113
86
  requirements:
114
87
  - - ">="
115
88
  - !ruby/object:Gem::Version
116
89
  version: '10.1'
117
- name: rake
118
- prerelease: false
119
90
  type: :development
91
+ prerelease: false
120
92
  version_requirements: !ruby/object:Gem::Requirement
121
93
  requirements:
122
94
  - - ">="
123
95
  - !ruby/object:Gem::Version
124
96
  version: '10.1'
125
97
  - !ruby/object:Gem::Dependency
98
+ name: rspec
126
99
  requirement: !ruby/object:Gem::Requirement
127
100
  requirements:
128
101
  - - ">="
129
102
  - !ruby/object:Gem::Version
130
103
  version: '3.2'
131
- name: rspec
132
- prerelease: false
133
104
  type: :development
105
+ prerelease: false
134
106
  version_requirements: !ruby/object:Gem::Requirement
135
107
  requirements:
136
108
  - - ">="
137
109
  - !ruby/object:Gem::Version
138
110
  version: '3.2'
139
111
  - !ruby/object:Gem::Dependency
112
+ name: rubocop
140
113
  requirement: !ruby/object:Gem::Requirement
141
114
  requirements:
142
115
  - - ">="
143
116
  - !ruby/object:Gem::Version
144
117
  version: 0.48.1
145
- name: rubocop
146
- prerelease: false
147
118
  type: :development
119
+ prerelease: false
148
120
  version_requirements: !ruby/object:Gem::Requirement
149
121
  requirements:
150
122
  - - ">="
@@ -161,7 +133,7 @@ files:
161
133
  - lib/cancancan/model_adapters/neo4j_adapter.rb
162
134
  - lib/cancancan/neo4j.rb
163
135
  - lib/cancancan/neo4j/active_record_disabler.rb
164
- - lib/cancancan/neo4j/association_conditions.rb
136
+ - lib/cancancan/neo4j/cypher_constructor.rb
165
137
  - lib/cancancan/neo4j/cypher_constructor_helper.rb
166
138
  - lib/cancancan/neo4j/rule_cypher.rb
167
139
  - lib/cancancan/neo4j/version.rb
@@ -169,7 +141,7 @@ homepage: https://github.com/CanCanCommunity/cancancan-neo4j
169
141
  licenses:
170
142
  - MIT
171
143
  metadata: {}
172
- post_install_message:
144
+ post_install_message:
173
145
  rdoc_options: []
174
146
  require_paths:
175
147
  - lib
@@ -184,9 +156,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
156
  - !ruby/object:Gem::Version
185
157
  version: '0'
186
158
  requirements: []
187
- rubyforge_project:
188
- rubygems_version: 2.6.14
189
- signing_key:
159
+ rubyforge_project:
160
+ rubygems_version: 2.7.6
161
+ signing_key:
190
162
  specification_version: 4
191
163
  summary: neo4j database adapter for CanCanCan.
192
164
  test_files: []
@@ -1,77 +0,0 @@
1
- require 'cancancan/neo4j/cypher_constructor_helper'
2
-
3
- module CanCanCan
4
- module Neo4j
5
- # Constructs cypher conditions for associations conditions hash
6
- class AssociationConditions
7
- attr_reader :conditions_string, :cypher_matches
8
-
9
- def initialize(options)
10
- @options = options
11
- @conditions_string = ''
12
- @cypher_matches = []
13
- construct_conditions
14
- end
15
-
16
- def construct_conditions
17
- @options[:asso_conditions].each do |association, conditions|
18
- relationship = association_relation(association)
19
- associations_conditions, model_conditions = CypherConstructorHelper.bifurcate_conditions(conditions)
20
- rel_length = associations_conditions.delete(:rel_length)
21
- current_path = append_path_to_conditions(relationship, model_conditions, rel_length)
22
- append_model_conditions(model_conditions, relationship, current_path)
23
- append_association_conditions(associations_conditions, relationship, rel_length)
24
- end
25
- end
26
-
27
- def association_relation(association)
28
- @options[:parent_class].associations[association]
29
- end
30
-
31
- def append_association_conditions(conditions, relationship, rel_length)
32
- return if conditions.blank?
33
- asso_conditions_obj = AssociationConditions.new(asso_conditions: conditions, parent_class: relationship.target_class, path: path_with_relationship(relationship, rel_length))
34
- append_and_to_conditions_string
35
- @conditions_string += asso_conditions_obj.conditions_string
36
- @cypher_matches += asso_conditions_obj.cypher_matches
37
- end
38
-
39
- def append_path_to_conditions(relationship, model_conditions, rel_length)
40
- target_class = relationship.target_class
41
- model_attr_exists = model_conditions.any? do |key, _|
42
- !target_class.associations_keys.include?(key)
43
- end
44
- to_node = CypherConstructorHelper.match_node_cypher(target_class) if model_attr_exists
45
- current_path = path_with_relationship(relationship, rel_length, to_node)
46
- if model_attr_exists
47
- append_matches(relationship)
48
- append_and_to_conditions_string
49
- @conditions_string += current_path
50
- end
51
- current_path
52
- end
53
-
54
- def append_matches(relationship)
55
- node_class = relationship.target_class
56
- @cypher_matches << CypherConstructorHelper.match_node_cypher(node_class)
57
- end
58
-
59
- def append_and_to_conditions_string
60
- @conditions_string += ' AND ' unless @conditions_string.blank?
61
- end
62
-
63
- def append_model_conditions(model_conditions, relationship, current_path)
64
- return if model_conditions.blank?
65
- con_string = CypherConstructorHelper.construct_conditions_string(model_conditions, relationship.target_class, current_path)
66
- append_and_to_conditions_string
67
- @conditions_string += con_string
68
- end
69
-
70
- def path_with_relationship(relationship, rel_length, to_node = nil)
71
- arrow_cypher = relationship.arrow_cypher(nil, {}, false, false, rel_length)
72
- to_node_label = CypherConstructorHelper.path_end_node(relationship)
73
- @options[:path] + arrow_cypher + (to_node || to_node_label)
74
- end
75
- end
76
- end
77
- end