Shawn Wilson Shawn Wilson - 6 months ago 13
Ruby Question

Generating a random string to save as an id, but continues to change on every page refresh?

I am trying to generate a Random 4-5 alphanumeric string to replace a standard user id, i have everything working, except every time I refresh the pages it generates and replaces the String. i have tried before_save and before_create but both seem to not work here.

My Model:

class Admin < ActiveRecord::Base
before_create :admin_ident

devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable,
:validatable, :confirmable, :lockable, :timeoutable

validates_uniqueness_of :admin_ident

def admin_ident
self.admin_ident = SecureRandom.hex(2).upcase
end
end


My Devise Registration Controller:

class Admin::Admins::RegistrationsController < Devise::RegistrationsController

private

def sign_up_params
params.require(:admin_admin).permit(:email, :password, :password_confirm, :admin_ident, :f_name, :m_name, :l_name, :dob, :street_number, :street_name, :unit_apt,
:quadrant, :city, :province, :postal_code, :home_tel, :moibile_tel, :office_tel, :office_ext, :company_email,
:position, :start_date, :end_date, :quit, :resigned, :terminated_cause, :terminated_wo_cause, :medical_leave,
:leave_of_abscense, :dl_number, :dl_class, :expiry, :conditions, :sl_number, :sl_certs, :issued, :expires, :emc_1_name,
:emc_1_tel, :emc_1_relationship, :emc_2_name, :emc_2_tel, :emc_2_relationship)
end

def account_update_params
params.require(:admin_admin).permit(:email, :password, :password_confirm, :current_password, :admin_ident, :f_name, :m_name, :l_name, :dob, :street_number, :street_name, :unit_apt,
:quadrant, :city, :province, :postal_code, :home_tel, :moibile_tel, :office_tel, :office_ext, :company_email,
:position, :start_date, :end_date, :quit, :resigned, :terminated_cause, :terminated_wo_cause, :medical_leave,
:leave_of_abscense, :dl_number, :dl_class, :expiry, :conditions, :sl_number, :sl_certs, :issued, :expires, :emc_1_name,
:emc_1_tel, :emc_1_relationship, :emc_2_name, :emc_2_tel, :emc_2_relationship)
end

def set_admin
@admin = Admin.find_by_admin_ident(params[:id])
end

end


My Routes.rb File:

## Namespace Resources
namespace :admin do
devise_for :admins, controllers: {
:registrations => 'admin/admins/registrations',
:sessions => 'admin/admins/sessions',
:passwords => 'admin/admins/passwords',
:confirmations => 'admin/admins/confirmations',
:unlocks => 'admin/admins/unlocks'
}
resources :admin_static
end

## Devise Scopes
devise_scope :admin do
authenticated do
root to: 'admin/admin_static#home', as: 'admin_authenticated_root'
end
end


not sure where I am going wrong here.. any assistance would be great!


Edit 1:


I am attempting to edit the admin/admin_static#home page

Answer

I think that it might be that you're using the same name for the field and the method that updates the field randomly.

before_create :generate_admin_ident
validates_uniqueness_of :generate_admin_ident

def generate_admin_ident
  begin
    self.admin_ident = SecureRandom.hex(2).upcase
    other_admin = Admin.find_by(admin_ident: self.admin_ident)
  end while other_admin
end

That should make all of the uses of admin_ident refer to the field and not the random generator.

Note that you're also using a validation to ensure uniqueness, however, this can cause arbitrary calls to create! or save to fail. Those should either be wrapped in begin..rescue..retry blocks, or the random generator should validate uniqueness itself.

The begin..end while loop and the other_admin code are intended to manually validate the uniqueness of the admin_ident generated by the method, and keep trying until it finds a unique value.