cancancan-neo4j 1.2.2 → 1.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.
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