Skip to main content

What is the correct way to convert virtual attribute to real one

Rails • Asked by Yurii Cherniavskyi
First of all the logic of my app. The user could have several profiles situationally, such as blogger, advertiser or manager and act with different profile different role. But during public registration, it could register only as blogger or advertiser. Add manager profile to the user can only admin.
So my main models:
class User < ApplicationRecord
  has_one :profile_manager, :class_name => 'Profile::Manager', dependent: :destroy, autosave: true
  has_one :profile_blogger, :class_name => 'Profile::Blogger', dependent: :destroy, autosave: true
  has_one :profile_advertiser, :class_name => 'Profile::Advertiser', dependent: :destroy, autosave: true

  accepts_nested_attributes_for :profile_manager,
                                :profile_blogger,
                                :profile_advertiser
end

class Profile::Base < ApplicationRecord
  self.abstract_class = true

  belongs_to :user
end
class Profile::Blogger < Profile::Base
end
class Profile::Advertiser < Profile::Base
end
class Profile::Manager < Profile::Base
end
To apply limitation on registration I create one more model with virtual attribute profile:
class RegistrableUser < User
  DEFAULT_PROFILE_MODEL_NAME = Profile::Blogger.model_name
  AVAILABLE_PROFILES_MODEL_NAMES = [Profile::Blogger.model_name, Profile::Advertiser.model_name]

  self.table_name = base_class.table_name

  attribute :profile, :string, default: DEFAULT_PROFILE_MODEL_NAME.param_key

  validates :profile, inclusion: {in: AVAILABLE_PROFILES_MODEL_NAMES.map(&:param_key),
                                  message: "%{value} is not a valid profile"}

  before_create :profile_decode

  private

  def profile_decode
    case self.profile
    when Profile::Blogger.model_name.param_key
      self.build_profile_blogger(active: true)
    when Profile::Advertiser.model_name.param_key
      self.build_profile_advertiser(active: true)
    end
  end
end
Seams it operates correctly. But I am not sure is it the correct implementation of such functionality in general and conversion virtual attribute to real profile property (by before_create hook) in particular case.

Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 27,623+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.