Safe to override save method in ActiveRecord? - ruby-on-rails

In a particular class that extends ActiveRecord::Base, I need to update a different ActiveRecord object whenever this one is created. Is it safe to override the save method and do the following in the save?
def save
super
other = self.other
other.name = self.name
other.save!
end
I'm worried about potential transaction related issues. I assume this would all be 1 transaction, if any part fails, everything is rolled back?

Is there a particular reason why you wouldn't use the hooks provided for this purpose?
You've got after_create, after_save, after_update, before_create, before_save, before_update - and a bunch of others. Wouldn't one of those be suitable?
In fact, given what you've said, it sounds like before_save is what you want, as you can catch any errors that occur whilst saving the second model and prevent the first one from being saved (by returning false from the before_save call).

Related

What happens during each of the ActiveRecord model lifecycle stages?

I cannot find documentation describing what happens during each of the ActiveRecord lifecycle stages. The Guide and API list the available callbacks.
How would I know which callback is appropriate if I don't know the state of the model, or what took place earlier in the lifecycle?
For example, when does the model get persisted, and gain an id? The guide lists callbacks:
3.1 Creating an Object
before_validation
after_validation
before_save
around_save
before_create
around_create
after_create
after_save
after_commit/after_rollback
So, I'm pretty sure that the model hasn't been persisted, and doesn't have and id, before before_save is called. I would expect the model to have and id before after_save is called. Unfortunately, I have no idea where, between those 2 calls the model was persisted, and gained its id.
EDIT
Again, this is purely one example. I have updated the question to clarify: "What happens during each of the ActiveRecord model lifecycle stages?"
Actually I can't provide you a link where all this stuff is explained.
But if I were you, I'd implement a method that will be invoked on each of these callbacks, and it could help to find out, when model gaines its id.
The "save" action is when the query to insert the record into the database is executed, and it is generally this action that will assign an id.
I can't say for sure that there aren't exceptions, but id's are usually assigned by the database during the insert process. The assigned id can be passed back to the application as part of the insert statement.

how exactly does rails callbacks work

I'm curious how exactly those callbacks work. If i initialize an object, and then use method save to throw it into my database, will before_create callback work?
Similar thing with before_save. is it called literally only before function save is being used, or will it be triggered also in case of using create method?
before_save will be triggered before you save a record. It doesn't matter whether you're creating or updating a record, your callback will be triggered. So, yes, it will also be triggered when you use the create method.
before_create is only triggered before creating a record, not before updating a record.
There is also before_update, which is only triggered before updating, but not before creating.
This doesn't depend on which method you use, it depends on whether the record was persisted before or not. In other words, it depends on whether you're updating or creating a record.
http://api.rubyonrails.org/v4.1.1/classes/ActiveRecord/Callbacks.html this url will help you find right answer for you. On this url you can also find the sequence for call back. Hope it helps you.

How to design mutually dependent models with callbacks

So I have 2 models A and B.
When A is saved or destroyed, B needs to be updated based on what happened with A.
When B is saved or destroyed, A needs to be updated based on what happened with B.
I can't just put 2 callbacks, it will lead to models having callbacks recursively. I don't need the callback to fire when model A is saved as result of firing B callback and vice versa.
What is the rails way to do this?
I had a similar situation, the best thing you can do is using a flag in your callbacks
class A
attr_accessor :is_updated_by_callback
after_commit :update_b
def update_b
return if is_updated_by_callback
b.is_updated_by_callback = true
b.update
end
end
and vice-versa
You can use update_columns in your callbacks:
e.g:
model A was saved. In the callback, you have something like this:
recordB.update_columns(:name => '')
update_column will not run any callback.
note: It will also not run validation, or update the updated_at field.

Log the user who destroyed a record using 'before_destroy' callback

I want to log the user who destroyed a record using before_destroy callback. But, I dont know how to pass arguments to before_destroy(and I am not sure if it is possible). Maybe I am dealing this in the wrong way. Any other perspective to do this will also do.
Create a virtual attribute on the Record model called destroyer or something.
Then you can do whatever you want with that attribute in your before_destroy callback.

Rails: create or update in model saving

I have a model (Bookmark) with two fields, call them A and B.
When creating a new model i have to perform a rather complex check on B and, if true update a Bookmark in the database (setting A to the one being passed) and abort the creation, if false just keep it on and create a new Bookmark.
So I set a before_create filter. The problem with the function called is that if I perform an update_attributes on a retrieved object from it and then return false (in order to abort the saving), the update is not performed (for some reason I don't know).
update_attributes returns true and there are no errors, but in the log i only see
SQL (0.2ms)
If i don't return false, the record is correctly updated, but it also inserts a new record (and I don't want this). Any help?
Canceling callbacks
If a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks defined as methods on the model, which are called last.
http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
When using callbacks, any call to update_attribute from within the before_create callback will bork it.
I was bitten unexpectedly by this as well. I think the source for this came from the rails api, in a one liner, or a blog post that escapes me right now, sorry.
This complicated call isn't a validation though?
Or maybe you can pull out the update_attribute and use it after the complicated logic?

Resources