cancancan-neo4j 1.0.2
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 +7 -0
- data/cancancan-neo4j.gemspec +32 -0
- data/lib/cancancan/model_adapters/neo4j_adapter.rb +131 -0
- data/lib/cancancan/neo4j.rb +6 -0
- data/lib/cancancan/neo4j/active_record_disabler.rb +7 -0
- data/lib/cancancan/neo4j/association_conditions.rb +74 -0
- data/lib/cancancan/neo4j/cypher_constructor_helper.rb +71 -0
- data/lib/cancancan/neo4j/rule_cypher.rb +63 -0
- data/lib/cancancan/neo4j/version.rb +7 -0
- metadata +192 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 148fb171b87ba1ffbb6445fbc94d784f17e0c7a5
|
4
|
+
data.tar.gz: 2a51eae6389c590145df0a17d06febd46d36cdf5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b91b481d4fd5c21a46679e639a66e01245edb84b1e0bbcf295f2a5ead6202b6a08e7fea7541f8331dc82f9a2d52fee32fcda8bf124f0351176aaf8fa94c4e7b5
|
7
|
+
data.tar.gz: d4d5388127d1ec21c0f107fa5fedf6b92e5187cb0fd5871cdc615091f8ba32da1dd8afda2c56dded956117f2903c0cfc6a8c037b67b3d2922a5d036752e122ce
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'cancancan/neo4j/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'cancancan-neo4j'
|
9
|
+
spec.version = CanCanCan::Neo4j::VERSION
|
10
|
+
spec.authors = ['Amit Suryavanshi']
|
11
|
+
spec.email = ['amitbsuryavanshi@gmail.com']
|
12
|
+
spec.homepage = 'https://github.com/CanCanCommunity/cancancan-neo4j'
|
13
|
+
spec.summary = 'neo4j database adapter for CanCanCan.'
|
14
|
+
spec.description = "Implements CanCanCan's rule-based record fetching using neo4j gem."
|
15
|
+
spec.platform = Gem::Platform::RUBY
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.files = `git ls-files lib init.rb cancancan-neo4j.gemspec`.split($INPUT_RECORD_SEPARATOR)
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'activemodel', '<5.2.0'
|
22
|
+
spec.add_dependency 'cancancan', '<=2.1.4'
|
23
|
+
spec.add_dependency 'neo4j', '>= 9.0.0'
|
24
|
+
|
25
|
+
spec.add_development_dependency 'bundler', '>= 1.3'
|
26
|
+
spec.add_development_dependency 'neo4j-community' if RUBY_PLATFORM =~ /java/
|
27
|
+
spec.add_development_dependency('neo4j-rake_tasks', '>= 0.3.0')
|
28
|
+
spec.add_development_dependency 'pry', '>= 0.11.3'
|
29
|
+
spec.add_development_dependency 'rake', '>= 10.1'
|
30
|
+
spec.add_development_dependency 'rspec', '>= 3.2'
|
31
|
+
spec.add_development_dependency 'rubocop', '>= 0.48.1'
|
32
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'cancancan/neo4j/cypher_constructor_helper'
|
2
|
+
require 'cancancan/neo4j/rule_cypher'
|
3
|
+
|
4
|
+
module CanCan
|
5
|
+
module ModelAdapters
|
6
|
+
# neo4j adapter for cancan
|
7
|
+
class Neo4jAdapter < AbstractAdapter
|
8
|
+
def database_records
|
9
|
+
return @model_class.where('false') if @rules.empty?
|
10
|
+
rule = @rules.first
|
11
|
+
return rule.conditions if override_scope
|
12
|
+
records_for_multiple_rules.distinct
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.for_class?(model_class)
|
16
|
+
model_class <= Neo4j::ActiveNode
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.override_conditions_hash_matching?(_subject, _conditions)
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.matches_conditions_hash?(subject, conditions)
|
24
|
+
base_class = subject.class
|
25
|
+
all_conditions_match?(subject, conditions, base_class)
|
26
|
+
end
|
27
|
+
|
28
|
+
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
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.matches_attribute_conditions?(conditions, subject)
|
55
|
+
return true if conditions.blank?
|
56
|
+
if subject.is_a?(Neo4j::ActiveNode::HasN::AssociationProxy)
|
57
|
+
subject.where(conditions).exists?
|
58
|
+
else
|
59
|
+
conditions.all? do |attribute, value|
|
60
|
+
subject.send(attribute) == value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.associations_conditions_match?(conditions, subject, base_class)
|
66
|
+
return true if conditions.blank?
|
67
|
+
conditions.all? do |association, conditions_hash|
|
68
|
+
current_model = base_class.associations[association].target_class
|
69
|
+
current_subject = subject.send(association)
|
70
|
+
all_conditions_match?(current_subject, conditions_hash, current_model)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def records_for_multiple_rules
|
77
|
+
base_query = base_query_proxy.query
|
78
|
+
cypher_options = construct_cypher_options
|
79
|
+
match_string = cypher_options[:matches].uniq.join(', ')
|
80
|
+
base_query = base_query.match(match_string) unless match_string.blank?
|
81
|
+
base_query
|
82
|
+
.proxy_as(@model_class, var_name(@model_class))
|
83
|
+
.where(cypher_options[:conditions])
|
84
|
+
end
|
85
|
+
|
86
|
+
def construct_cypher_options
|
87
|
+
default_options = { conditions: '', matches: [] }
|
88
|
+
@rules.reverse.each_with_object(default_options) do |rule, options|
|
89
|
+
rule_options = { rule: rule, model_class: @model_class }
|
90
|
+
rule_cypher = CanCanCan::Neo4j::RuleCypher.new(rule_options)
|
91
|
+
CanCanCan::Neo4j::CypherConstructorHelper
|
92
|
+
.append_and_or_to_conditions(options, rule_cypher)
|
93
|
+
options[:conditions] += ('(' + rule_cypher.rule_conditions + ')')
|
94
|
+
options[:matches] += rule_cypher.cypher_matches
|
95
|
+
options
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def base_query_proxy
|
100
|
+
@model_class.as(var_name(@model_class))
|
101
|
+
end
|
102
|
+
|
103
|
+
def override_scope
|
104
|
+
conditions = @rules.map(&:conditions).compact
|
105
|
+
return unless conditions.any? { |condition| condition.is_a?(Neo4j::ActiveNode::Query::QueryProxy) }
|
106
|
+
return conditions.first if conditions.size == 1
|
107
|
+
raise_override_scope_error
|
108
|
+
end
|
109
|
+
|
110
|
+
def raise_override_scope_error
|
111
|
+
rule_found = @rules.detect { |rule| rule.conditions.is_a?(Neo4j::ActiveNode::Query::QueryProxy) }
|
112
|
+
raise Error,
|
113
|
+
'Unable to merge an ActiveNode scope with other conditions. '\
|
114
|
+
"Instead use a hash for #{rule_found.actions.first} #{rule_found.subjects.first} ability."
|
115
|
+
end
|
116
|
+
|
117
|
+
def var_name(model_class)
|
118
|
+
CanCanCan::Neo4j::CypherConstructorHelper.var_name(model_class)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
module Neo4j
|
125
|
+
module ActiveNode
|
126
|
+
# simplest way to add `accessible_by` to all ActiveNode models
|
127
|
+
module ClassMethods
|
128
|
+
include CanCan::ModelAdditions::ClassMethods
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,74 @@
|
|
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
|
+
current_path = append_path_to_conditions(relationship, model_conditions)
|
21
|
+
append_model_conditions(model_conditions, relationship, current_path)
|
22
|
+
append_association_conditions(associations_conditions, relationship)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def association_relation(association)
|
27
|
+
@options[:parent_class].associations[association]
|
28
|
+
end
|
29
|
+
|
30
|
+
def append_association_conditions(conditions, relationship)
|
31
|
+
return if conditions.blank?
|
32
|
+
asso_conditions_obj = AssociationConditions.new(asso_conditions: conditions, parent_class: relationship.target_class, path: path_with_relationship(relationship))
|
33
|
+
append_and_to_conditions_string
|
34
|
+
@conditions_string += asso_conditions_obj.conditions_string
|
35
|
+
@cypher_matches += asso_conditions_obj.cypher_matches
|
36
|
+
end
|
37
|
+
|
38
|
+
def append_path_to_conditions(relationship, model_conditions)
|
39
|
+
target_class = relationship.target_class
|
40
|
+
model_attr_exists = model_conditions.any? do |key, _|
|
41
|
+
!target_class.associations_keys.include?(key)
|
42
|
+
end
|
43
|
+
end_node = model_attr_exists ? CypherConstructorHelper.match_node_cypher(target_class) : '()'
|
44
|
+
current_path = @options[:path] + relationship.arrow_cypher + end_node
|
45
|
+
if model_attr_exists
|
46
|
+
append_matches(relationship)
|
47
|
+
append_and_to_conditions_string
|
48
|
+
@conditions_string += current_path
|
49
|
+
end
|
50
|
+
current_path
|
51
|
+
end
|
52
|
+
|
53
|
+
def append_matches(relationship)
|
54
|
+
node_class = relationship.target_class
|
55
|
+
@cypher_matches << CypherConstructorHelper.match_node_cypher(node_class)
|
56
|
+
end
|
57
|
+
|
58
|
+
def append_and_to_conditions_string
|
59
|
+
@conditions_string += ' AND ' unless @conditions_string.blank?
|
60
|
+
end
|
61
|
+
|
62
|
+
def append_model_conditions(model_conditions, relationship, current_path)
|
63
|
+
return if model_conditions.blank?
|
64
|
+
con_string = CypherConstructorHelper.construct_conditions_string(model_conditions, relationship.target_class, current_path)
|
65
|
+
append_and_to_conditions_string
|
66
|
+
@conditions_string += con_string
|
67
|
+
end
|
68
|
+
|
69
|
+
def path_with_relationship(relationship)
|
70
|
+
@options[:path] + relationship.arrow_cypher + '()'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module CanCanCan
|
2
|
+
module Neo4j
|
3
|
+
# Cypher query constructs
|
4
|
+
class CypherConstructorHelper
|
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
|
+
path + base_class.associations[key].arrow_cypher + '()'
|
39
|
+
end
|
40
|
+
|
41
|
+
def condition_for_id(base_class, variable_name, value)
|
42
|
+
id_property = base_class.id_property_name
|
43
|
+
if id_property == :neo_id
|
44
|
+
"ID(#{variable_name})=#{value}"
|
45
|
+
else
|
46
|
+
variable_name + '.' + id_property.to_s + '=' + "'#{value}'"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def var_name(class_constant)
|
51
|
+
class_constant.name.downcase.split('::').join('_')
|
52
|
+
end
|
53
|
+
|
54
|
+
def bifurcate_conditions(conditions)
|
55
|
+
conditions.partition { |_, value| value.is_a?(Hash) }.map(&:to_h)
|
56
|
+
end
|
57
|
+
|
58
|
+
def append_and_or_to_conditions(cypher_options, rule_cypher)
|
59
|
+
conditions_string = cypher_options[:conditions]
|
60
|
+
connector = if conditions_string.blank?
|
61
|
+
''
|
62
|
+
else
|
63
|
+
rule_cypher.conditions_connector
|
64
|
+
end
|
65
|
+
connector += 'NOT' if rule_cypher.append_not_to_conditions?
|
66
|
+
cypher_options[:conditions] = conditions_string + connector
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'cancancan/neo4j/cypher_constructor_helper'
|
2
|
+
require 'cancancan/neo4j/association_conditions'
|
3
|
+
|
4
|
+
module CanCanCan
|
5
|
+
module Neo4j
|
6
|
+
# Constructs cypher conditions for rule and cypher match classes
|
7
|
+
class RuleCypher
|
8
|
+
attr_reader :rule_conditions, :cypher_matches
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
@options = options
|
12
|
+
@rule_conditions = ''
|
13
|
+
@cypher_matches = []
|
14
|
+
construct_cypher_conditions
|
15
|
+
end
|
16
|
+
|
17
|
+
def construct_cypher_conditions
|
18
|
+
if @options[:rule].conditions.blank?
|
19
|
+
condition_for_rule_without_conditions
|
20
|
+
else
|
21
|
+
set_cypher_options
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
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
|
+
private
|
34
|
+
|
35
|
+
def rule_conditions_blank?
|
36
|
+
@options[:rule].conditions.blank?
|
37
|
+
end
|
38
|
+
|
39
|
+
def condition_for_rule_without_conditions
|
40
|
+
@rule_conditions = @options[:rule].base_behavior ? '(true)' : '(false)'
|
41
|
+
end
|
42
|
+
|
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)
|
48
|
+
end
|
49
|
+
|
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
|
56
|
+
end
|
57
|
+
|
58
|
+
def default_path
|
59
|
+
CypherConstructorHelper.match_node_cypher(@options[:model_class])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
metadata
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cancancan-neo4j
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Amit Suryavanshi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-04-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "<"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: 5.2.0
|
19
|
+
name: activemodel
|
20
|
+
prerelease: false
|
21
|
+
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
|
+
prerelease: false
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "<="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.1.4
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 9.0.0
|
47
|
+
name: neo4j
|
48
|
+
prerelease: false
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 9.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.3'
|
61
|
+
name: bundler
|
62
|
+
prerelease: false
|
63
|
+
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
|
+
prerelease: false
|
77
|
+
type: :development
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 0.3.0
|
89
|
+
name: neo4j-rake_tasks
|
90
|
+
prerelease: false
|
91
|
+
type: :development
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.3.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 0.11.3
|
103
|
+
name: pry
|
104
|
+
prerelease: false
|
105
|
+
type: :development
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.11.3
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '10.1'
|
117
|
+
name: rake
|
118
|
+
prerelease: false
|
119
|
+
type: :development
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '10.1'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '3.2'
|
131
|
+
name: rspec
|
132
|
+
prerelease: false
|
133
|
+
type: :development
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '3.2'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: 0.48.1
|
145
|
+
name: rubocop
|
146
|
+
prerelease: false
|
147
|
+
type: :development
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.48.1
|
153
|
+
description: Implements CanCanCan's rule-based record fetching using neo4j gem.
|
154
|
+
email:
|
155
|
+
- amitbsuryavanshi@gmail.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- cancancan-neo4j.gemspec
|
161
|
+
- lib/cancancan/model_adapters/neo4j_adapter.rb
|
162
|
+
- lib/cancancan/neo4j.rb
|
163
|
+
- lib/cancancan/neo4j/active_record_disabler.rb
|
164
|
+
- lib/cancancan/neo4j/association_conditions.rb
|
165
|
+
- lib/cancancan/neo4j/cypher_constructor_helper.rb
|
166
|
+
- lib/cancancan/neo4j/rule_cypher.rb
|
167
|
+
- lib/cancancan/neo4j/version.rb
|
168
|
+
homepage: https://github.com/CanCanCommunity/cancancan-neo4j
|
169
|
+
licenses:
|
170
|
+
- MIT
|
171
|
+
metadata: {}
|
172
|
+
post_install_message:
|
173
|
+
rdoc_options: []
|
174
|
+
require_paths:
|
175
|
+
- lib
|
176
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
requirements: []
|
187
|
+
rubyforge_project:
|
188
|
+
rubygems_version: 2.6.14
|
189
|
+
signing_key:
|
190
|
+
specification_version: 4
|
191
|
+
summary: neo4j database adapter for CanCanCan.
|
192
|
+
test_files: []
|