views:

709

answers:

4

Hello,

I have a User model and a Friendship-Model.

class Friendship < ActiveRecord::Base
  belongs_to :sender, :class_name=>'User', :foreign_key=>'sender_id'
  belongs_to :receiver, :class_name=>'User', :foreign_key=>'receiver_id'

  validates_presence_of :receiver_id, :sender_id
  validates_associated :receiver, :sender
end

class User < ActiveRecord::Base
  has_many :sent_friendships, :class_name => "Friendship", :foreign_key => "sender_id", :dependent => :destroy
  has_many :received_friendships, :class_name => "Friendship", :foreign_key => "receiver_id", :dependent => :destroy
end

and one of my rspec-test is

describe Friendship do

  before(:each) do
    @valid_attributes = {
      :sender_id => 1,
      :receiver_id => 2,
      :accepted_at => nil
    }
  end

  it "should not be valid with non-existant receiver_id" do
    f = Friendship.new(@valid_attributes)
    f.receiver_id = 99999
    f.should_not be_valid
  end
end

The test shouldnt be valid, because there is no User with user_id 9999. But the test say's the friendship-model is valid.

Why the hell?

EDIT:

But I want to test like mentioned -> without assigning the sender directly. Isn't that possible??

A: 

The Rails documentation for validates_associtated states the following:

NOTE: This validation will not fail if the association hasn‘t been assigned. If you want to ensure that the association is both present and guaranteed to be valid, you also need to use validates_presence_of.

You havn't assigned the association. Modify your test as follows and it should pass:

it "should not be valid with non-existant receiver_id" do
  f = Friendship.new(@valid_attributes)
  f.receiver_id = 99999
  f.receiver = nil  # Note this line
  f.should_not be_valid
end
Christoph Schiessl
A: 

Hm..

after I found only this blog entry and a wont-fix-ticket in rails lighthouse:

Blog-entry with solution

Lighthouse-wont-fix-ticket

i switched to my own solution:

class Friendship < ActiveRecord::Base
  belongs_to :sender, :class_name=>'User', :foreign_key=>'sender_id'
  belongs_to :receiver, :class_name=>'User', :foreign_key=>'receiver_id'

  validates_presence_of :receiver_id, :sender_id

  validate :sender_exists
  validate :receiver_exists

  protected
  def sender_exists
    errors.add("sender_id", "not existant") unless User.exists?(self.sender_id)
  end  
end
Lichtamberg
+3  A: 

If you want your model to work that way, change this:

validates_presence_of :receiver_id, :sender_id

to this:

validates_presence_of :receiver, :sender
Elliot Nelson
+1  A: 

There's also an old plugin floating around that does this... validates_existence_of.

http://blog.hasmanythrough.com/2007/7/14/validate-your-existence

Ian Terrell