module RandomUniqueId::ClassMethods

Collection of methods that will end as class methods of ActiveRecord::Base.

@see ActiveSupport::Concern

Public Instance Methods

belongs_to(*attrs) click to toggle source

Augment the ActiveRecord belongs_to to also define rid accessors. For example: if you blog post belongs_to an author, on top of the methods author, author=, author_id and author_id=, it’ll also have author_rid and author_rid= that allow you to retrieve the RID of the author or set another author by using the RID.

@param attrs [Array] same as the parameters for ActiveRecord::Associations::ClassMethods.belongs_to except that

passing rid: false will prevent the rid accessors from beign defined.

@see ActiveRecord::Associations::ClassMethods.belongs_to

Calls superclass method
# File lib/random_unique_id.rb, line 66
def belongs_to(*attrs)
  define_rid_method = attrs[1].try(:delete, :rid)
  super.tap do
    if define_rid_method != false
      relationship_name = attrs[0]
      rel = reflections[relationship_name] || reflections[relationship_name.to_s]

      return if rel.options[:polymorphic] # If we don't know the class, we cannot find the record by rid.

      class_name = rel.options[:class_name] || relationship_name.to_s.classify
      related_class = class_name.constantize
      define_rid_accessors(related_class, relationship_name) if related_class.attribute_names.include? "rid"
    end
  end
end
has_random_unique_id(options={}) click to toggle source

Mark a model as containing a random unique id. A field called rid of type string is required. It’s recommended that it’s indexed and unique. For example, you could add it to a migration like this:

def up
  add_column :posts, :rid, :string
  add_index :posts, :rid, :unique
end

and then to the model like this:

class Post
  has_random_unique_id
  # ... other stuff
end

@param options [Hash] generation options, same as RandomUniqueID.config, in case the generation method or minimum

length needs to be overridden for one specific model
# File lib/random_unique_id.rb, line 52
def has_random_unique_id(options={})
  options = RandomUniqueId.config.merge(options)
  before_validation :populate_rid_field, if: Proc.new { |r| r.send(options[:field]).blank? }
  add_rid_related_validations(options)
  add_rid_related_methods(options)
end
populate_random_unique_ids() { |record, rid_just_populated| ... } click to toggle source

Populate all the blank rids in a table. This is useful when adding rids to a table that already has data in it. For example:

def up
  add_column :posts, :rid, :string
  add_index :posts, :rid, :unique
  say_with_time "Post.populate_random_unique_ids" do
    Post.reset_column_information
    Post.populate_random_unique_ids { print "."}
  end
end

This method uses update_column to avoid running validations and callbacks. It will not change existing rids, so it’s safe to call several times and a failure (even without a transaction) is not catastrophic.

# File lib/random_unique_id.rb, line 95
def populate_random_unique_ids
  find_each do |record|
    rid_just_populated = false
    if record.send(record.random_unique_id_options[:field]).blank?
      record.populate_rid_field
      record.update_column(record.random_unique_id_options[:field], record.send(record.random_unique_id_options[:field]))
      rid_just_populated = true
    end
    yield(record, rid_just_populated) if block_given?
  end
end

Private Instance Methods

define_rid_accessors(related_class, relationship_name) click to toggle source

Defines the setter and getter for the RID of a relationship.

@param related_class [Class] class in which the RID methods are going to be defined. @param relationship_name [String] name of the relationship for which the RID methods are going to be defined. @see RandomUniqueId::ClassMethods.belongs_to

# File lib/random_unique_id.rb, line 128
def define_rid_accessors(related_class, relationship_name)
  define_method("#{relationship_name}_rid") do
    self.send(relationship_name).try(random_unique_id_options[:field])
  end

  define_method("#{relationship_name}_rid=") do |rid|
    record = related_class.find_by_rid(rid)
    self.send("#{relationship_name}=", record)
    record
  end
end