module Voltron::Encryptable::InstanceMethods

Public Instance Methods

assign_attributes(new_attributes) click to toggle source
Calls superclass method
# File lib/voltron/encryptable.rb, line 66
def assign_attributes(new_attributes)
  belongs = self.class.reflect_on_all_associations(:belongs_to).map { |b| { column: "#{b.name}_id".to_sym, class_name: (b.options[:class_name] || b.name).to_s.classify } }

  belongs.each do |belong|
    begin
      klass = belong[:class_name].safe_constantize
      value = new_attributes[belong[:column]]
      next if !klass.has_encrypted_id? || value.blank?
      record = klass.find(value)
      new_attributes[belong[:column]] = record.id
    rescue NameError, ActiveRecord::RecordNotFound
    end
  end

  super(new_attributes)
end
find_id() click to toggle source
# File lib/voltron/encryptable.rb, line 107
def find_id
  # Helps determine the min/max value. For example if amount is 1100, min will be 1024, if amount is 947, min will be 1
  amount = Voltron::Id.count.to_f

  # The range of ids from which we try to find an unused id, i.e. - (1..1024), (1025..2048), (2049..3073)
  factor = 1024.to_f

  # Get the min and max value of the range segment
  min = (((amount/factor).floor*factor) + 1).to_i
  max = (((amount+1)/factor).ceil*factor).to_i

  # Get all ids in the determined range segment, these are the ids we cannot choose from
  used = Voltron::Id.where(id: min..max).pluck(:id)
  # Get the candidates, an array of values from min to max, subtracting the used values from above
  candidates = ((min..max).to_a - used).shuffle
  # Get the first candidate, the first value off the shuffled array
  candidate = candidates.shift

  # Check for blacklisted words given the candidate id
  while crypt.blacklisted?(candidate) do
    # If id chosen is a blacklisted word, insert it as a placeholder record and try again
    Voltron::Id.create(id: candidate, resource_id: 0, resource_type: :blacklist)

    # If no more candidates to choose from, re-run find_id, it will get a new set of candidates from the next segment
    return find_id if candidates.empty?

    # Pick the next candidate
    candidate = candidates.shift
  end

  # The id chosen is good, not a blacklisted word. Use it
  candidate
end
reload(options = nil) click to toggle source
# File lib/voltron/encryptable.rb, line 141
def reload(options = nil)
  clear_aggregation_cache
  clear_association_cache
  self.class.connection.clear_query_cache

  fresh_object =
    if options && options[:lock]
      self.class.unscoped { self.class.lock(options[:lock]).find_by(id: encryptable.resource_id) }
    else
      self.class.unscoped { self.class.find(encryptable.resource_id, bypass: true) }
    end

  @attributes = fresh_object.instance_variable_get("@attributes")
  @new_record = false
  self
end
to_param() click to toggle source
Calls superclass method
# File lib/voltron/encryptable.rb, line 100
def to_param
  return super if encryptable.nil?

  crypt = Voltron::Encrypt.new
  crypt.encode(encryptable.id)
end
update_attributes(attributes) click to toggle source
Calls superclass method
# File lib/voltron/encryptable.rb, line 83
def update_attributes(attributes)
  belongs = self.class.reflect_on_all_associations(:belongs_to).map { |b| { column: "#{b.name}_id".to_sym, class_name: (b.options[:class_name] || b.name).to_s.classify } }

  belongs.each do |belong|
    begin
      klass = belong[:class_name].safe_constantize
      value = attributes[belong[:column]]
      next if !klass.has_encrypted_id? || value.blank?
      record = klass.find(value)
      attributes[belong[:column]] = record.id
    rescue NameError, ActiveRecord::RecordNotFound
    end
  end

  super(attributes)
end

Private Instance Methods

crypt() click to toggle source
# File lib/voltron/encryptable.rb, line 160
def crypt
  @crypt ||= Voltron::Encrypt.new
end