I'm using "acts_as_tree" plugin for my user messaging thread feature on my website. I have a method that makes deleting selected messages possible. The messages don't actually get deleted. Their sender_status or recipient_status columns get set to 1 depending on what user is the sender or recipient of the message.
Anyway if both users have those status's set to one then that last line makes sure the message row is completely moved from the database. Now this is fine as long as it's not the parent message being deleted. If the parent message deleted then the children that haven't been selected for deletion won't be accessible anymore.
Here is the method:
def delete_all_users_selected_messages(message_ids, user_id, parent_id)
Message.where(:id => message_ids, :sender_id => user_id).update_all(:sender_status => 1)
Message.where(:id => message_ids, :recipient_id => user_id).update_all(:recipient_status => 1)
Message.delete_all(:sender_status => 1, :recipient_status => 1, :parent_id => parent_id).where("id != ?", parent_id)
end
It's quite obvious what I'm trying to do. I need to have the parent ignored. So where the primary key is equal to the parent_id means that row is a parent (normally the parent_id is nil but I needed it set to the primary keys value for some other reason, long story and not important). Anyway is there an SQL statement I can add on to the end of the last line in tat method? To make sure it only deletes messages where the id of the row is not equal to the parent_id?
I can arrange for the parent_id row to never be permitted for deletion unless the actual thread (MessageThreads table that references the messages tables conversations) is deleted.
Any way how can I make it so this parent row is ignored when that delete_all method is run?
Kind regards
Basically destroy runs any callbacks on the model while delete doesn't. Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted). Returns the frozen instance.
Method: ActiveRecord::Relation#destroy_all Returns the collection of objects that were destroyed; each will be frozen, to reflect that no changes should be made (since they can't be persisted).
Nowadays in Rails 4, you can do:
Model.where.not(attr: "something").delete_all
and
Model.where.not(attr: "something").destroy_all
And don't forget about difference:
destroy
method. Instantiates all the records and destroys them one at a time, so with a large dataset, this could be slowdestroy
method. Callbacks are not called.Why not use association from the parent record, something like this?
Message.where(:id => parent_id).first
.children.where(:sender_status => 1, :recipient_status => 1)
.delete_all
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With