mongoid/mongoid — Issue #1464: Record is not saved to the DB, model reports false on #new_record?
Author: snitko
Created: 2011-12-01 00:13:10+00:00
State: open

I have a `Message` and `MessageThread` classes. After creating a new `Message` (in the after_create callback), a new `MessageThread` must be created, unless it already exists for the participants of the discussion.

Problem is, when I use browser to create a new `Message`, `MessageThread` record is not created in the db, although the model reports `false` on #new_record? The fascinating thing is that everything works as expected (`MessageThread` record gets created in the db) with the same development environment in the console.

Here's a full code for both models:

class Message

include Mongoid::Document
include Mongoid::Timestamps

field :text
field :is_read, :type => Boolean, :default => false
field :notification_sent, :type => Boolean, :default => false
belongs_to :author, :class_name => "Account", :inverse_of => :sent_messages
belongs_to :recipient, :class_name => "Account", :inverse_of => :received_messages

index [:author_id, :recipient_id]

validates_presence_of :text, :author, :recipient

after_create do
mt = MessageThread.all_in(:accounts => [author_id, recipient_id]).first
if mt.nil?
mt = MessageThread.new(:accounts => [author_id, recipient_id])
end
if recipient.notifications.unread_messages == false
recipient.notifications = recipient.notifications.merge({ :unread_messages => true })
recipient.save
end
mt.set_recent_message(id, recipient)
mt.save
end

end

class MessageThread

include Mongoid::Document
include Mongoid::Timestamps

field :accounts, :type => Array; index :accounts
field :recent_messages, :type => Hash, :default => {}
validates_presence_of :accounts
validate :validate_uniqueness_of_accounts, :on => :create

def recent_message_id(me)
m = recent_messages[me.id.to_s]
# if there's no recent message for me from the other person,
# than return my most recent message to the other person.
m.blank? ? recent_messages[recipient_id(me).to_s] : m
end

def set_recent_message(message_id, recipient)
rm = { recipient.id.to_s => message_id }
write_attribute(:recent_messages, recent_messages.merge(rm))
end

def recipient_id(me)
@recipient ||= accounts[0] == me.id ? accounts[1] : accounts[0]
end

after_create do
puts "********************************************************************"
puts self.new_record? # -> false
p MessageThread.last # -> `nil` if the message was created using a web-interface,
# but returns an actual record when a message is created in console.
# This, of course, assumes there was 0 MessageThreads before.
puts "********************************************************************"
end

private

# Manually checking unqueness here, because standart method
# checks not just the contents of the array, but also its order.
def validate_uniqueness_of_accounts
errors.add(:accounts, "MessageThread already exists for these accounts") if MessageThread.all_in(:accounts => [accounts[0], accounts[1]]).first
end

end

Since the behavior is only present when I use browser, I'm not sure this has to be a mongoid issue, but I was just hoping someone would help to shed light on this. Thanks.