简体   繁体   中英

Rails 4 Authentication from scratch: before_create vs before_save

Can someone explain why before_save :encrypt_password creates a password_hash and password_salt in my database, but before_create :encrypt_password does not? Is there some Rails 4 or Rails specification I'm missing? Code snippet below.

include MembersHelper

class Member < ActiveRecord::Base
include ActiveModel::Validations

has_many :parents, through: :reverse_relationships, source: :parent
has_many :children, through: :relationships, source: :child
has_many :relationships, foreign_key: "parent_id", dependent: :destroy
has_many :reverse_relationships, foreign_key: "child_id", class_name: Relationship, dependent: :destroy
has_many :spouses, through: :spouse_relationships, source: :spouse
has_many :spouse_relationships, foreign_key: "member_id", dependent: :destroy
has_many :images

accepts_nested_attributes_for :parents, reject_if: proc { |attributes| attributes['first_name'].blank? && attributes['first_name'].blank? }
accepts_nested_attributes_for :spouses, reject_if: proc { |attributes| attributes['first_name'].blank? && attributes['first_name'].blank? }
accepts_nested_attributes_for :children, reject_if: proc { |attributes| attributes['first_name'].blank? && attributes['first_name'].blank? }

attr_accessor :password

#####
before_save :encrypt_password ##### this does not work if i change it to before_create
#####
before_save :nil_or_downcase
before_create :nil_or_downcase
after_create :set_oldest_ancestor
before_create { create_token(:remember_token) }

before_destroy [ :set_ancestor_for_children, :destroy_spouse_id_of_spouse ]

def encrypt_password
    if password.present?
        self.password_salt = BCrypt::Engine.generate_salt
        self.password_hash = BCrypt::Engine.hash_secret( password, password_salt)
    end
end

In a "create" method, you are initializing AND saving at the same time.

When you have a "save" method, you must first initialize and then save it.

So, i guess this does not work for before_create, just because still this moment you don´t have a password in a instance initialized.

And in "before_save", it works because if you are saving something, you already have initialized a instance with the password, and then it could be encrypted.

Remembering: create = new + save at the same time, so before_create you don´t have anything. and save must go with something already initialized.

I hope I have been clear!

Unfortunately, both before_create :encrypt_password and before_save :encrypt_password are properly saving the encrypted string into the database, as is :after_validation. There must have been some bug that I accidentally fixed, or one that I haven't and has simply disappeared for the moment.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM