Ruby on Rails Callback, What Is Difference Between :Before_Save and :Before_Create

Ruby on Rails Callback, what is difference between :before_save and :before_create?

In a create operation under Rails, there are six callbacks before the database operation, and two after. In order, these are:

  1. before_validation
  2. before_validation_on_create
  3. after_validation
  4. after_validation_on_create
  5. before_save
  6. before_create


    DATABASE INSERT
  7. after_create
  8. after_save

Update operations have exactly the same set, except read update instead of create everywhere (and UPDATE instead of INSERT).

From this, you can see that validation is carried out before the before_save and before_create callbacks.

The before_save occurs slightly before the before_create. To the best of my knowledge, nothing happens between them; but before_save will also fire on Update operations, while before_create will only fire on Creates.

Call back before save : SystemStackError: stack level too deep

Stack level too deep indicates it went to infinite loop. If you save anything in before save, after save, before create, after create, before update, after update which call callback again it will cause stack level too deep.

In above code i found that set_st_point is called in before create and saving it which caused here Stack level too deep. Data is not saving after setting also that must be some other issue that you have to check if once you set 'lonlat ' some other place it is resetting it.

Once simple fix is in after create you can say

 .update_column('lonlat',"POINT(#{longitude} #{latitude})")

update column will not call any callback this must be there in after create.

Is :on = :create valid for a before_save callback in Rails 3.2.3

You're right, there is no :on option for before_save callback.
But, I don't understand, why use before_save instead of before_create.
before_create callback will be called right after before_save.

Of course, you can use before_save :callback_method, :if => :new_record?. But I personally don't like this solution - what if I need to add conditions in the :if option?

If one have a dependency between before_save and before_create callbacks, I`d suggest, to combine 2 callbacks. For instance (pseudocode):

class MyModel < ActiveRecord::Base
before_create :prepare_x
before_save :do_something_with_x

def prepare_x
@x = 10
end


# will not work, because `prepare_x` called after `do_something_with_x`
def do_something_with_x
@a = 100 / @x
end
end

# ||
# ||
# \/

class MyModel < ActiveRecord::Base

before_save :do_something_with_x

def do_something_with_x
@x = 10 if new_record?
@a = 100 / @x
end
end

setting mandatory field automatically in Rails from Model callback, when and how?

I'm struggling with the correct way to implement this

The most efficient way will be to use an ActiveRecord callback hook, such as you've posted:

#app/models/category.rb
class Category < ActiveRecord::Base
before_create :your_action

private

def your_action
#fires before create
end
end

but this seems to late in the flow

As mentioned in the comments, you can see the order of the callbacks (and thus their order in the flow):

Sample Image

Thus, if you want to populate some data before you validate, and then validate that data, you'll be best using the before_validation callback:

#app/models/category.rb
class Category < ActiveRecord::Base
before_validation :set_position_number, on: :create
validates :position, ______________

private

def set_position_number
highest = Category.maximum(:position)
self.position = highest.to_i + 1
end
end

Remember, a Rails model just populates certain attributes which are then to be either saved to the db, or validated. Rails does not care where those attributes come from; populating them before_validation is a good a source as the controller.

I am unable to find callback methods in .NET core 2.0

I don't know the first thing about Ruby but I'm guessing the callbacks on the models are the equivalent of events in c#.

class Program
{
static void Main(string[] args)
{
CustomerRepository repo = new CustomerRepository();

// wire up the BeforeSave event as needed
repo.BeforeSave += c => Console.WriteLine("Customer {0} will be saved...", c.Name);

// wire up the AfterSave event to send an email or whatever you need
repo.AfterSave += c => Console.WriteLine("Customer {0} was saved sucessfully.", c.Name);

// create a new customer
Customer cust = new Customer { ID = 1, Name = "Sam" };

// save the customer which will fire the before/after events
repo.Save(cust);

Console.ReadLine();
}
}


public class CustomerRepository
{
public event Action<Customer> BeforeSave;
public event Action<Customer> AfterSave;

public virtual void Save(Customer customer)
{
// Invoke the before save event on the repo
BeforeSave?.Invoke(customer);

// do some save stuff
Console.WriteLine("Customer {0} is being saved...", customer.Name);

// Invoke the after save event
AfterSave?.Invoke(customer);
}
}


public class Customer
{
// Put events here or in a base class if you wish,
// just as is shown in the repository class
// but that is probably not a good design

public int ID { get; set; }
public string Name { get; set; }
}

Before Save callback on associations

You can either use this patch that adds the "touch" functionality to the has_one association or just define another after_save callback in the User model and "touch" the Company instance explicitly there.

Rails 3: Ensure before_save callback is called after others

You could make the callback you want executed last an around_save callback. Check out the list of available callbacks and see if you can simply use a different callback "bucket" for some of your callbacks to ensure they are executed in the desired order.

If you still end up with multiple before_save callbacks and need one to trigger last, you may want to create custom callbacks, like maybe define_model_callbacks :split_save, registering your regular before_save callbacks as before_split_save callbacks, the one you want executed last as a after_split_save callback, and then just a single before_save callback that runs those two groups of callbacks (run_callbacks :split_save). See ActiveModel::Callbacks for more on how to do this.



Related Topics



Leave a reply



Submit