require_relative "base/has_uuids"
module Uuids
# Defines the +has_uuids+ model class helper.
module Base
extend ActiveSupport::Concern
# Methods added to the ActiveRecord model.
module ClassMethods
private
# The helper defines:
#
# +uuids+:: the +ActiveRecord+ association with a record's uuids.
# +uuid+:: a virtual attribute that returns the first value of uuids.
# uuid=:: new uuid setter.
# uuids=:: uuids group setter.
# by_uuid:: the +ActiveRecord+ relation scope.
#
# @example
# class City < ActiveRecord::Base
# include Uuids::Base
#
# has_uuids
# end
#
# city = City.create!
#
# city.uuids.map(&:value)
# # => 51f50391-fcd2-4f69-aab7-6ef31b29c379
#
# city.uuid
# # => 51f50391-fcd2-4f69-aab7-6ef31b29c379
#
# city.uuid = "51f50391-fcd2-4f69-aab7-6ef31b29c379"
#
# city.uuids = [
# "51f50391-fcd2-4f69-aab7-6ef31b29c379",
# "3ea8fd89-232f-4ed1-90b5-743da173cd7d"
# ]
#
# City.by_uuid("51f50391-fcd2-4f69-aab7-6ef31b29c379").to_a == [city]
# # => true
def has_uuids
include Uuids::Base::HasUuids
has_many_uuids
after_initialize :add_default_uuid
before_destroy :prevent_destruction
validates :uuids, presence: true, on: :update
end
# The helper defines both the getter and setter for object, associated
# by uuid.
#
# @example
# class City < ActiveRecord::Base
# include Uuids::Base
#
# belongs_by_uuid_to :state, class: State
# end
#
# city = City.new
# city.state_uuid = "12345678-90ab-cdef-1234-567890abcdef"
#
# city.state.class # => State
# city.state.uuid # => "12345678-90ab-cdef-1234-567890abcdef"
#
# city.state = State.new uuid: "fedcba98-7654-3210-fedc-ba9876543210"
# city.state.uuid # => "fedcba98-7654-3210-fedc-ba9876543210"
#
# @param [String, Symbol] name The name of the attribute.
# @param [Hash] options The options for the association.
# @option options [Class] :class The model of the attribute.
# @option options [String] :class_name The name of the attribute's model.
def belongs_by_uuid_to(name, options = {})
class_name = options[:class] || options[:class_name].constantize
BelongsTo.add self, name, class_name
end
end
private
# Prevents the module usage outside an ActiveRecord model.
def self.included(klass)
unless klass.ancestors.include? ActiveRecord::Base
fail TypeError.new("#{ klass.name } isn't an ActiveRecord model.")
end
end
end
end