Ask A Question

Notifications

You’re not receiving notifications from this thread.

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

Yurii Cherniavskyi asked in Rails
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.
Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 82,464+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.