Search code examples
ruby-on-railsformsgetter-settervirtual-attribute

how to fill virtual form fields with non-split attribue


I have a form with 3 virtual attributes (phoneAreaCode, phonePrefix and phoneSuffix) splitting a phone number into segments which gets joined together and saved to the database as phoneNum.

When a user goes to update their profile, most of the fields are filled in, but the virtual fields are not. I tried using what I thought was a getter to make it work, but I can't figure out what I'm missing. On that note, I'm using a nested form with address attributes from a second model, however, when these attributes are nil the form fields don't display in the update view at all. Is there a way to make those display even if they are nil? The nested form attributes appear in the sign up view, and both the sign up and update view are rendering the same form from a layout. The model is below.

class User < ActiveRecord::Base
  attr_accessor :phoneAreaCode, :phonePrefix, :phoneSuffix

  attr_accessible :MOS, :dateOfBirth, :ets_pcsDate, :firstName, 
  :lastName, :middleInitial, :phoneNum, :phoneAreaCode, :phonePrefix,
  :phoneSuffix, :rank, :email, :password, :password_confirmation, 
  :address_attributes

  has_secure_password
  has_one :address, dependent: :destroy

  accepts_nested_attributes_for :address


  before_save {  |user| user.email = email.downcase  }
  before_save :create_remember_token
  before_save :create_phoneNum

  validates :rank,      presence: true
  validates :firstName,     presence: true, length: {  maximum: 15  }
  validates :lastName,  presence: true, length: {  maximum: 20  }
  validates :middleInitial, presence: true, length: {  maximum: 1  }

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email,presence: true,  format: {  with: VALID_EMAIL_REGEX  },
                        uniqueness: {  case_sensitive: false  }

  validates :dateOfBirth,    presence: true
  VALID_MOS_REGEX = /\A\d{2}[a-zA-Z]\z/
  validates :MOS,           presence: true, 
                                    format: {  with: VALID_MOS_REGEX }
  validates :ets_pcsDate,       presence: true

  VALIDATE_AREA_PREFIX_REGEX = /\A\d{3}\z/
  validates :phoneAreaCode,     presence: true,  
                                    format: { with: VALIDATE_AREA_PREFIX_REGEX }                               
  validates :phonePrefix,           presence: true,
                                    format: { with: VALIDATE_AREA_PREFIX_REGEX }
  VALIDATE_SUFFIX_REGEX = /\A\d{4}\z/                                       
  validates :phoneSuffix,           presence: true,
                                    format: { with: VALIDATE_SUFFIX_REGEX }
  validates :password,      length: {  minimum: 6  }
  validates :password_confirmation, presence: true


  private
    def create_phoneNum
      self.phoneNum = [phoneAreaCode, 
                      phonePrefix, phoneSuffix].join(' ')
    end

    def create_phoneNum=(phoneNum)
      split = phoneNum.split(' ', 3)
      self.phoneAreaCode = split.first
      self.phonePrefix = split.second
      self.phoneSuffix = split.last
    end

    def create_remember_token
      self.remember_token = SecureRandom.urlsafe_base64
    end
end

Solution

  • Works with

    def phoneAreaCode
      if phoneNum != nil
         @phoneAreaCode ||= self.phoneNum.split(' ')[0]
      else
         @phoneAreaCode
      end
    end
    
    def phonePrefix
      if phoneNum != nil
        @phonePrefix ||= self.phoneNum.split(' ')[1]
      else
        @phonePrefix
      end
    end
    
    def phoneSuffix
      if phoneNum != nil
        @phoneSuffix ||= self.phoneNum.split(' ')[2]
      else
        @phoneSuffix
      end
    end