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