-
Notifications
You must be signed in to change notification settings - Fork 276
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1038 from neo4jrb/creates_unique_with_props
Arguments for ActiveRel.creates_unique, new Association `unique` options
- Loading branch information
Showing
17 changed files
with
516 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
module Neo4j::ActiveNode::HasN | ||
class Association | ||
class RelFactory | ||
[:start_object, :other_node_or_nodes, :properties, :association].tap do |accessors| | ||
attr_reader(*accessors) | ||
private(*accessors) | ||
end | ||
|
||
def self.create(start_object, other_node_or_nodes, properties, association) | ||
factory = new(start_object, other_node_or_nodes, properties, association) | ||
factory._create_relationship | ||
end | ||
|
||
def _create_relationship | ||
creator = association.relationship_class ? :rel_class : :factory | ||
send(:"_create_relationship_with_#{creator}") | ||
end | ||
|
||
private | ||
|
||
def initialize(start_object, other_node_or_nodes, properties, association) | ||
@start_object = start_object | ||
@other_node_or_nodes = other_node_or_nodes | ||
@properties = properties | ||
@association = association | ||
end | ||
|
||
def _create_relationship_with_rel_class | ||
Array(other_node_or_nodes).each do |other_node| | ||
node_props = _nodes_for_create(other_node, :from_node, :to_node) | ||
association.relationship_class.create(properties.merge(node_props)) | ||
end | ||
end | ||
|
||
def _create_relationship_with_factory | ||
Array(other_node_or_nodes).each do |other_node| | ||
wrapper = _rel_wrapper(properties) | ||
base = _match_query(other_node, wrapper) | ||
factory = Neo4j::Shared::RelQueryFactory.new(wrapper, wrapper.rel_identifier) | ||
factory.base_query = base | ||
factory.query.exec | ||
end | ||
end | ||
|
||
def _match_query(other_node, wrapper) | ||
nodes = _nodes_for_create(other_node, wrapper.from_node_identifier, wrapper.to_node_identifier) | ||
Neo4j::Session.current.query.match_nodes(nodes) | ||
end | ||
|
||
def _nodes_for_create(other_node, from_node_id, to_node_id) | ||
nodes = [@start_object, other_node] | ||
nodes.reverse! if association.direction == :in | ||
{from_node_id => nodes[0], to_node_id => nodes[1]} | ||
end | ||
|
||
def _rel_wrapper(properties) | ||
Neo4j::ActiveNode::HasN::Association::RelWrapper.new(association, properties) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class Neo4j::ActiveNode::HasN::Association | ||
# Provides the interface needed to interact with the ActiveRel query factory. | ||
class RelWrapper | ||
include Neo4j::Shared::Cypher::RelIdentifiers | ||
include Neo4j::Shared::Cypher::CreateMethod | ||
|
||
attr_reader :type, :association | ||
attr_accessor :properties | ||
private :association | ||
alias_method :props_for_create, :properties | ||
|
||
def initialize(association, properties = {}) | ||
@association = association | ||
@properties = properties | ||
@type = association.relationship_type(true) | ||
creates_unique(association.creates_unique_option) if association.unique? | ||
end | ||
|
||
def persisted? | ||
false | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
module Neo4j::Shared | ||
module Cypher | ||
module CreateMethod | ||
def create_method | ||
creates_unique? ? :create_unique : :create | ||
end | ||
|
||
def creates_unique(option = :none) | ||
option = :none if option == true | ||
@creates_unique = option | ||
end | ||
|
||
def creates_unique_option | ||
@creates_unique || :none | ||
end | ||
|
||
def creates_unique? | ||
!!@creates_unique | ||
end | ||
alias_method :unique?, :creates_unique? | ||
end | ||
|
||
module RelIdentifiers | ||
extend ActiveSupport::Concern | ||
|
||
[:from_node, :to_node, :rel].each do |element| | ||
define_method("#{element}_identifier") do | ||
instance_variable_get(:"@#{element}_identifier") || element | ||
end | ||
|
||
define_method("#{element}_identifier=") do |id| | ||
instance_variable_set(:"@#{element}_identifier", id.to_sym) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
module Neo4j::Shared | ||
class FilteredHash | ||
class InvalidHashFilterType < Neo4j::Neo4jrbError; end | ||
VALID_SYMBOL_INSTRUCTIONS = [:all, :none] | ||
VALID_HASH_INSTRUCTIONS = [:on] | ||
VALID_INSTRUCTIONS_TYPES = [Hash, Symbol] | ||
|
||
attr_reader :base, :instructions, :instructions_type | ||
|
||
def initialize(base, instructions) | ||
@base = base | ||
@instructions = instructions | ||
@instructions_type = instructions.class | ||
validate_instructions!(instructions) | ||
end | ||
|
||
def filtered_base | ||
case instructions | ||
when Symbol | ||
filtered_base_by_symbol | ||
when Hash | ||
filtered_base_by_hash | ||
end | ||
end | ||
|
||
private | ||
|
||
def filtered_base_by_symbol | ||
case instructions | ||
when :all | ||
[base, {}] | ||
when :none | ||
[{}, base] | ||
end | ||
end | ||
|
||
def filtered_base_by_hash | ||
behavior_key = instructions.keys.first | ||
filter_keys = keys_array(behavior_key) | ||
[filter(filter_keys, :with), filter(filter_keys, :without)] | ||
end | ||
|
||
def key?(filter_keys, key) | ||
filter_keys.include?(key) | ||
end | ||
|
||
def filter(filter_keys, key) | ||
filtering = key == :with | ||
base.select { |k, _v| key?(filter_keys, k) == filtering } | ||
end | ||
|
||
def keys_array(key) | ||
instructions[key].is_a?(Array) ? instructions[key] : [instructions[key]] | ||
end | ||
|
||
def validate_instructions!(instructions) | ||
fail InvalidHashFilterType, "Filtering instructions #{instructions} are invalid" unless VALID_INSTRUCTIONS_TYPES.include?(instructions.class) | ||
clazz = instructions_type.name.downcase | ||
return if send(:"valid_#{clazz}_instructions?", instructions) | ||
fail InvalidHashFilterType, "Invalid instructions #{instructions}, valid options for #{clazz}: #{send(:"valid_#{clazz}_instructions")}" | ||
end | ||
|
||
def valid_symbol_instructions?(instructions) | ||
valid_symbol_instructions.include?(instructions) | ||
end | ||
|
||
def valid_hash_instructions?(instructions) | ||
valid_hash_instructions.include?(instructions.keys.first) | ||
end | ||
|
||
def valid_symbol_instructions | ||
VALID_SYMBOL_INSTRUCTIONS | ||
end | ||
|
||
def valid_hash_instructions | ||
VALID_HASH_INSTRUCTIONS | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.