views:

55

answers:

2

I have a model named Tickets that being saved to the database even when invalid. This is stopping me from using validations to help prevent duplicate data being saved to the DB. In script/console

>> Ticket.last.valid? 
=> False
>> Ticket.first.valid?
=> False

If I try to see what errors are associated with this invalid object

>> Ticket.last.errors.each{|attr,msg| puts "#{attr} - #{msg}\n" }
=> {}

So does anyone know how it's possible to save an invalid object to the database, and how can I find what is making the object invalid?

Ticket.rb (model)

   class Ticket < ActiveRecord::Base

  belongs_to :whymail
  belongs_to :forms

  attr_accessible :to_email, :to_email, :from_email, :subject, :body


  validates_uniqueness_of   :to_email, :scope => [:body, :from_email]
  validates_presence_of     :to_email
  validates_presence_of     :from_email
  validates_presence_of     :subject
  validates_presence_of     :body



  def after_create

    if self.valid?
       whymail = Whymail.find(:first, :include => :user, :conditions => ['(email = ?)', self.to_email.upcase ] )    
      if !whymail.nil?
        self.whymail_id = whymail.id
        self.save
        MyMailer.deliver_forward(whymail.user.email, self.from_email, self.to_email, self.subject, self.body)        
      end
    end
  end

end

One part of this question was answered, second was not. Can anyone see problems with this model that may allow it to save even though it is invalid??

+1  A: 

It is possible to skip validations. How are you saving it? Is it part of a nested form?

In any case, you should look at the errors like this:

>>t = Ticket.last
>>t.valid?
>>t.errors.each{|attr,msg| puts "#{attr} - #{msg}\n" }

The way you have it above, you are getting a new object with the second Ticket.last call and validation hasn't been run on that one, so you can't see what the errors are.

MattMcKnight
That totally makes sense, it says that i have an error on the email address which i would expect ( i don't want any emails saved that have the same to, from, and body). Is there something wrong with my model that enables it to save even though invalid? I am saving via Ticket.create inside of an action mailer receive method.
ThinkBohemian
I am wondering if it became invalid after it was saved via some kind of timing thing. validates_uniqueness_of is not 100% reliable. I recommend putting a constraint in the database as well.
MattMcKnight
A: 

Try something like:

t = Ticket.last
t.save
puts t.errors.full_messages.inspect

The errors object won't be populated until you try to save the activerecord object.

Joe Van Dyk