Forum: Rails deployment Rails Object in DB is Invalid

Posted by 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?
Posted by 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?
Posted by 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?
Posted by 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.
Posted by 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....
Posted by 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.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.