Skip to content

Commit

Permalink
Fixed validation on Rails relationship - If a rails relationship is i…
Browse files Browse the repository at this point in the history
…nvalid then the start and end node of that relationship will also be invalid
  • Loading branch information
andreasronge committed Apr 10, 2011
1 parent bae7d50 commit 0144836
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 20 deletions.
4 changes: 3 additions & 1 deletion lib/neo4j/rails/relationship.rb
Expand Up @@ -4,6 +4,8 @@ class Relationship
include Neo4j::RelationshipMixin

attr_reader :type
attr_writer :start_node
attr_writer :end_node

index :_classname

Expand Down Expand Up @@ -33,7 +35,7 @@ def id
_java_rel.nil? || neo_id.nil? ? nil : neo_id.to_s
end

def start_node
def start_node
@start_node ||= _java_rel && _java_rel.start_node
end

Expand Down
10 changes: 6 additions & 4 deletions lib/neo4j/rails/relationships/storage.rb
Expand Up @@ -133,21 +133,23 @@ def valid?(context, validated_nodes)
return true if validated_nodes.include?(@node)
all_valid = true

!@outgoing_rels.each do |rel|
@outgoing_rels.each do |rel|
start_node = rel.start_node
end_node = rel.end_node
#start_node, end_node = end_node, start_node if @node == end_node

validated_nodes << start_node << end_node
if !end_node.valid?(context, validated_nodes)
all_valid = false
all_valid = false
start_node.errors[@rel_type.to_sym] ||= []
start_node.errors[@rel_type.to_sym] << end_node.errors.clone
elsif !start_node.valid?(context, validated_nodes)
all_valid = false

all_valid = false
end_node.errors[@rel_type.to_sym] ||= []
end_node.errors[@rel_type.to_sym] << start_node.errors.clone
end

all_valid = false if !rel.valid?
end
all_valid
end
Expand Down
86 changes: 71 additions & 15 deletions spec/rails/relationship_spec.rb
Expand Up @@ -892,19 +892,75 @@ def to_s
@start_node.rels(:foobar).outgoing.size.should == 1
end
end
end
# context "other_node_rel" do
# subject { @start_node.other_node_rel }
#
# before(:each) do
# @start_node = NodeWithRelationship.new
# @end_node = Neo4j::Rails::Model.new
# @start_node.other_node = @end_node
# end
#
# #it { should be_a(RelationshipWithNoProperty) }
# it_should_behave_like "a relationship model"
# end
#
#end

describe "Relationship validation" do
before(:all) do
@actor_class = create_model
@movie_class = create_model
@role_class = create_rel_model
@role_class.property :character
@role_class.validates_presence_of :character
@actor_class.has_n(:acted_in).relationship(@role_class)
end

it "validation when invalid" do
actor = @actor_class.new
movie = @movie_class.new
actor.acted_in << movie
actor.outgoing(:acted_in).size.should == 1
movie.incoming(:acted_in).size.should == 1
actor.acted_in.size.should == 1
actor.save.should be_false
actor.outgoing(:acted_in).size.should == 1
movie.incoming(:acted_in).size.should == 1
actor.acted_in.size.should == 1
rel = actor.acted_in_rels.first
rel.errors.size.should == 1
rel.should_not be_persisted
@actor_class.find(actor.neo_id).should be_nil
@movie_class.find(movie.neo_id).should be_nil
actor.reload
movie.reload
actor.outgoing(:acted_in).size.should == 0
movie.incoming(:acted_in).size.should == 0
actor.acted_in.size.should == 0
end


it "validation when invalid with depth 2" do
pending "not sure how this will work"
actor = @actor_class.new
movie = @movie_class.new
actor.acted_in << movie
role = actor.acted_in_rels.first
role.character = 'micky mouse'
actor2 = @actor_class.new
actor2.acted_in << movie
actor.save.should be_false # should probably return false here since we tried to save relationship for actor2
end

it "validation when valid" do
actor = @actor_class.new
movie = @movie_class.new
actor.acted_in << movie
role = actor.acted_in_rels.first
role.character = 'micky mouse'
actor.outgoing(:acted_in).size.should == 1
movie.incoming(:acted_in).size.should == 1
actor.acted_in.size.should == 1
actor.save.should be_true
actor.outgoing(:acted_in).size.should == 1
movie.incoming(:acted_in).size.should == 1
actor.acted_in.size.should == 1
rel = actor.acted_in_rels.first
rel.errors.size.should == 0
rel.should be_persisted
actor = @actor_class.find(actor.neo_id)
movie = @movie_class.find(movie.neo_id)
actor.outgoing(:acted_in).size.should == 1
movie.incoming(:acted_in).size.should == 1
actor.acted_in.size.should == 1
end

end
end
10 changes: 10 additions & 0 deletions spec/spec_helper.rb
Expand Up @@ -105,6 +105,16 @@ def create_model(base_class = Neo4j::Model, &block)
klass
end

def create_rel_model(base_class = Neo4j::Rails::Relationship, &block)
@@_rel_counter ||= 1
name ||= "Relationship_#{@@_rel_counter}"
@@_rel_counter += 1
klass = Class.new(base_class)
TempModel.set(klass, name)
klass.class_eval &block if block
klass
end

def create_node_mixin_subclass(parent_clazz = Object, &block)
klass = Class.new(parent_clazz)
TempModel.set(klass)
Expand Down

0 comments on commit 0144836

Please sign in to comment.