require 'active_support/core_ext/string/inflections' module UniverseCompiler module Entity module RelationsManagement def has_one(target_entity_type_or_class, name: nil, with_reverse_method: nil, unique: false) target_entity_type = normalize_entity_type target_entity_type_or_class field_name = relation_field_name name, target_entity_type define_constraint field_name, :has_one, target_entity_type return unless with_reverse_method define_constraint_for_reverse_method :has_one, target_entity_type, field_name, with_reverse_method, unique end def has_many(target_entity_type_or_class, name: nil, with_reverse_method: nil, unique: false) target_entity_type = normalize_entity_type target_entity_type_or_class field_name = relation_field_name name, target_entity_type field_name = field_name.to_s.pluralize.to_sym if name.nil? define_constraint field_name, :has_many, target_entity_type return unless with_reverse_method define_constraint_for_reverse_method :has_many, target_entity_type, field_name, with_reverse_method, unique end private def relation_field_name(name, target_entity_type) case name when NilClass target_entity_type when String, Symbol name.to_sym end end def define_constraint_for_reverse_method(relation_type, target_entity_type, source_field_name, with_reverse_method, unique) reverse_method_name = case with_reverse_method when TrueClass "referenced_from_#{self.entity_type}_#{source_field_name}".to_sym when String, Symbol with_reverse_method.to_sym end target_class = UniverseCompiler::Entity::TypeManagement.type_class_mapping(target_entity_type) method_creation_data = { source_entity: self.entity_type, source_field: source_field_name, relation_type: relation_type, unique_result: unique } target_class.define_constraint reverse_method_name, :reverse_method, method_creation_data true end end end end