diff --git a/lib/neo4j/active_rel/persistence.rb b/lib/neo4j/active_rel/persistence.rb index 366d2ae46..9aa1863cb 100644 --- a/lib/neo4j/active_rel/persistence.rb +++ b/lib/neo4j/active_rel/persistence.rb @@ -54,10 +54,10 @@ def create!(*args) def confirm_node_classes [from_node, to_node].each do |node| - check = from_node == node ? :_from_class : :_to_class - next if self.class.send(check) == :any - unless self.class.send(check) == node.class - raise ModelClassInvalidError, "Node class was #{node.class}, expected #{self.class.send(check)}" + type = from_node == node ? :_from_class : :_to_class + next if allows_any_class?(type) + unless class_as_constant(type) == node.class + raise ModelClassInvalidError, "Node class was #{node.class}, expected #{self.class.send(type)}" end end end @@ -68,5 +68,21 @@ def _create_rel(from_node, to_node, *args) set_classname(props) from_node.create_rel(type, to_node, props) end + + def class_as_constant(type) + given_class = self.class.send(type) + case + when given_class.is_a?(String) + given_class.constantize + when given_class.is_a?(Symbol) + given_class.to_s.constantize + else + given_class + end + end + + def allows_any_class?(type) + self.class.send(type) == :any || self.class.send(type) == false + end end -end +end \ No newline at end of file diff --git a/lib/neo4j/active_rel/property.rb b/lib/neo4j/active_rel/property.rb index f948d3f6b..e9347e50b 100644 --- a/lib/neo4j/active_rel/property.rb +++ b/lib/neo4j/active_rel/property.rb @@ -1,4 +1,3 @@ - module Neo4j::ActiveRel module Property extend ActiveSupport::Concern @@ -7,7 +6,7 @@ module Property %w[to_node from_node].each do |direction| define_method("#{direction}") { instance_variable_get("@#{direction}") } define_method("#{direction}=") do |argument| - raise FrozenRelError, "Relationship start/end nodes cannot be changed once persisted" if self.persisted? + raise FrozenRelError, 'Relationship start/end nodes cannot be changed once persisted' if self.persisted? instance_variable_set("@#{direction}", argument) end end @@ -15,18 +14,18 @@ module Property alias_method :start_node, :from_node alias_method :end_node, :to_node + # @return [String] a string representing the relationship type that will be created def type self.class._type end - def initialize(attributes={}, options={}) + def initialize(attributes = {}, options = {}) super(attributes, options) send_props(@relationship_props) unless @relationship_props.nil? end module ClassMethods - # Extracts keys from attributes hash which are relationships of the model # TODO: Validate separately that relationships are getting the right values? Perhaps also store the values and persist relationships on save? def extract_association_attributes!(attributes) @@ -43,10 +42,12 @@ def extract_association_attributes!(attributes) alias_method :start_class, :from_class alias_method :end_class, :to_class + # @param type [String] sets the relationship type when creating relationships via this class def type(type = nil) @rel_type = type end + # @return [String] a string representing the relationship type that will be created def _type @rel_type end @@ -54,15 +55,13 @@ def _type def load_entity(id) Neo4j::Node.load(id) end - end private - def load_nodes(start_node=nil, end_node=nil) + def load_nodes(start_node = nil, end_node = nil) @from_node = RelatedNode.new(end_node) @to_node = RelatedNode.new(start_node) end - end -end +end \ No newline at end of file diff --git a/spec/unit/active_rel/persistence_spec.rb b/spec/unit/active_rel/persistence_spec.rb index e11df86ac..903591c55 100644 --- a/spec/unit/active_rel/persistence_spec.rb +++ b/spec/unit/active_rel/persistence_spec.rb @@ -98,25 +98,49 @@ class ThatClass; end let(:r) { clazz.new(from_node: this_class_node, to_node: that_class_node) } - it 'does not raise an error' do + def model_stubs_and_expectations expect(this_class_node).to receive(:class).and_return(ThisClass) clazz.any_instance.stub(:_create_rel) clazz.any_instance.stub(:init_on_load) expect{r.save}.not_to raise_error end - context 'with :any types' do + it 'does not raise an error' do + model_stubs_and_expectations + end + + it 'converts strings to constants' do + clazz.from_class 'ThisClass' + model_stubs_and_expectations + end + + it 'converts symbols to constants' do + clazz.from_class :ThisClass + model_stubs_and_expectations + end + + context 'with :any or false types' do before do clazz.from_class :any clazz.to_class :any end - it 'does not check the classes of the nodes' do + def any_stubs_and_expectations expect(this_class_node).not_to receive(:class) expect(that_class_node).not_to receive(:class) clazz.any_instance.stub(:_create_rel) clazz.any_instance.stub(:init_on_load) - expect{r.save}.not_to raise_error + expect { r.save }.not_to raise_error + end + + it 'does not check the classes of the nodes' do + any_stubs_and_expectations + end + + it 'accepts false instead of :any' do + clazz.from_class false + clazz.to_class false + any_stubs_and_expectations end end end diff --git a/spec/unit/active_rel/property_spec.rb b/spec/unit/active_rel/property_spec.rb index c51263bc0..cf4a520e9 100644 --- a/spec/unit/active_rel/property_spec.rb +++ b/spec/unit/active_rel/property_spec.rb @@ -55,23 +55,15 @@ expect(clazz.instance_variable_get(:@to_class)).to eq Object end end - - context 'when passed invalid classes' do - it 'is pending' - end - - context 'when passed :any' do - it 'is pending' - end end end describe 'class methods' do describe 'extract_relationship_attributes!' do it 'returns the from and to keys and values' do - expect(clazz.extract_association_attributes!({to_node: 'test', from_node: 'test', name: 'chris'})).to eq(to_node: 'test', from_node: 'test') - expect(clazz.extract_association_attributes!({to_node: 'test', name: 'chris'})).to eq(to_node: 'test') - expect(clazz.extract_association_attributes!({from_node: 'test', name: 'chris'})).to eq(from_node: 'test') + expect(clazz.extract_association_attributes!({ to_node: 'test', from_node: 'test', name: 'chris' })).to eq(to_node: 'test', from_node: 'test') + expect(clazz.extract_association_attributes!({ to_node: 'test', name: 'chris' })).to eq(to_node: 'test') + expect(clazz.extract_association_attributes!({ from_node: 'test', name: 'chris' })).to eq(from_node: 'test') end end