Forum: Rails deployment Rails Object in DB is Invalid

71ee1809f53df0a2b4dac0530f630933?d=identicon&s=25 Richard Schneeman (snowmaninthesun)
on 2009-12-09 16:14
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 its possible to save an invalid object to the
database, and how can i find what is making the object invalid?
73c04e9ef9ca435c5b19a2e765ae6d20?d=identicon&s=25 Max Williams (max-williams)
on 2009-12-18 17:36
I encountered a problem like this before and it turned out to be due to
a callback which was returning false.  Unbeknownst to me, if a callback
returns false then the whole chain halts.  Do you have any callbacks
that fire before validation, and if so could any of them be returning
false?
71ee1809f53df0a2b4dac0530f630933?d=identicon&s=25 Richard Schneeman (snowmaninthesun)
on 2009-12-18 20:08
Max Williams wrote:
> I encountered a problem like this before and it turned out to be due to
> a callback which was returning false.  Unbeknownst to me, if a callback
> returns false then the whole chain halts.  Do you have any callbacks
> that fire before validation, and if so could any of them be returning
> false?

Hmm...i only have a after_create callback. Here is my ticket.rb model

http://pastie.org/749098

Do any major problems jump out at you ?

Even stranger, i turned on debugger level logging, and i only see one
insertion into the database, yet was getting two database entries (but
again only sometimes).

When i tried writing to a file to help trace down the problem, i haven't
been able to reproduce the issue since: http://pastie.org/749104

I call the create like this:

Ticket.find(:first, :conditions => {:from_email => from_email, :to_email
=> to_email, :body => message})||Ticket.create(:subject => subject,
:from_email => from_email, :to_email => to_email, :body => message)


Any Ideas?
73c04e9ef9ca435c5b19a2e765ae6d20?d=identicon&s=25 Max Williams (max-williams)
on 2009-12-18 21:58
the whole create/after_create situation isn't relevant to the question
really.  The question is 'how come something fails validation but has no
errors'.

You've got a complicated kind of situation going on with the
attr_accessibles which i don't really understand.  I can see that you've
got :to_email in there twice which is wrong but probably not the source
of this particular problem.

I don't really understand what this is for:

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

You're saying that the combination of :to_email, :body and :from_email
has to be unique?  Maybe that's the problem but you'd expect to get an
error raised if it wasn't a unique combination.
71ee1809f53df0a2b4dac0530f630933?d=identicon&s=25 Richard Schneeman (snowmaninthesun)
on 2009-12-18 22:17
Thanks for the catch on the attr_accessible. We actually figured out
that it was causing errors, I was wasn't checking the error correctly.

http://stackoverflow.com/questions/1874569/rails-o...

You are correct

"validates_uniqueness_of   :to_email, :scope => [:body, :from_email]"


This does throw an error on to_email only if the body and from_email are
also not unique. And this is the error i get when i check the errors on
the duplicate objects in the database

I have tested this validation using rspec, and it behaves correctly....
73c04e9ef9ca435c5b19a2e765ae6d20?d=identicon&s=25 Max Williams (max-williams)
on 2009-12-18 23:50
err, so is the mystery solved now or what?  Is the original problem
still persisting?  I noticed something that is confusing the issue:

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

Here, you load a record out of the db with Ticket.last, then call valid
on it.  Then, you load it out of the db AGAIN, from scratch, with
Ticket.last again.  So, it doesn't have any errors because the current
object hasn't had .valid called on it:  it's only after calling .valid
that it would have anything in .errors.  Anything loaded fresh from the
db will never have any errors.

So, instantiate an object and do all of your stuff with that.  BTW, i
usually call errors.full_messages to see the errors.  eg

ticket = Ticket.last
ticket.valid?
ticket.errors.full_messages

Try that.
This topic is locked and can not be replied to.