rosalynnas
rosalynnas

Reputation: 423

Rails 6 before save callback not fired

I am trying to assign a random number to an attribute named position before my Product objects are saved. I cannot get the callback to work properly. There are no errors in the console, it just silently fails.

Here is my model

class Product < ApplicationRecord
validates_presence_of :position
before_save {
    assign_position
}

private
    def assign_position
        self.position = rand(150)
    end
end

This is my schema

create_table "products", force: :cascade do |t|
    t.string "name"
    t.integer "position"
end

Here is an example seed I'm using to test the before save callback.

Product.create(name: "Rose Deep Hydration Facial Toner")

There are no errors but the console output when I check after creating the seed

irb(main):079:0> Product.find_by_name("Rose Deep Hydration Facial Toner").position
Product Load (1.8ms)  SELECT "products".* FROM "products" WHERE "products"."name" = $1 ORDER BY "products"."created_at" DESC LIMIT $2  [["name", "Rose Deep Hydration Facial Toner"], ["LIMIT", 1]]
=> nil

I have other callbacks in the application that work just fine. I can't figure out why this one is not working.

Upvotes: 1

Views: 621

Answers (1)

mu is too short
mu is too short

Reputation: 434585

Your problem is that validations happen before before_save callbacks are triggered. You have this:

validates_presence_of :position

but position will still be nil when that validation is checked.

I think you want to use a before_validation callback instead of before_save:

class Product < ApplicationRecord
  before_validation :assign_position
  validates_presence_of :position

private

  def assign_position
    self.position = rand(150)
  end
end

Keep in mind that assign_position will get called every time you validate a Product so updating a typo in the name (for example) will change the position. You might want to leave the position alone if it is already set or if you're altering an existing instance.

Upvotes: 3

Related Questions