Class: Railsmith::BaseService::AssociationDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/railsmith/base_service/association_definition.rb

Overview

Value object representing a single declared association on a service.

Stores the association name, kind (:has_many, :has_one, :belongs_to), the associated service class, and options governing cascading behaviour.

Constant Summary collapse

ASYNC_INCOMPATIBLE_DEPENDENT =

Dependent modes that imply cascading service-layer behavior on parent destruction. Async nested writes cannot honor these guarantees because the job runs after the parent transaction has committed, so combining them is rejected up-front.

%i[destroy nullify restrict].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, kind, service:, **options) ⇒ AssociationDefinition

Returns a new instance of AssociationDefinition.

Parameters:

  • name (Symbol, String)

    association key

  • kind (Symbol)

    :has_many, :has_one, or :belongs_to

  • service (Class)

    Railsmith::BaseService subclass for the associated records

  • options (Hash)

    supported keys: :foreign_key, :dependent, :optional, :validate, :async



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/railsmith/base_service/association_definition.rb', line 22

def initialize(name, kind, service:, **options)
  @name         = name.to_sym
  @kind         = kind.to_sym
  @service_class = service
  @foreign_key  = options[:foreign_key]&.to_sym
  @dependent    = (options.fetch(:dependent, :ignore) || :ignore).to_sym
  @optional     = options.fetch(:optional, false)
  @validate     = options.fetch(:validate, true)
  @async        = options.fetch(:async, false) ? true : false

  validate_async_dependent_compatibility!

  freeze
end

Instance Attribute Details

#asyncObject (readonly)

Returns the value of attribute async.



16
17
18
# File 'lib/railsmith/base_service/association_definition.rb', line 16

def async
  @async
end

#dependentObject (readonly)

Returns the value of attribute dependent.



16
17
18
# File 'lib/railsmith/base_service/association_definition.rb', line 16

def dependent
  @dependent
end

#foreign_keyObject (readonly)

Returns the value of attribute foreign_key.



16
17
18
# File 'lib/railsmith/base_service/association_definition.rb', line 16

def foreign_key
  @foreign_key
end

#kindObject (readonly)

Returns the value of attribute kind.



16
17
18
# File 'lib/railsmith/base_service/association_definition.rb', line 16

def kind
  @kind
end

#nameObject (readonly)

Returns the value of attribute name.



16
17
18
# File 'lib/railsmith/base_service/association_definition.rb', line 16

def name
  @name
end

#optionalObject (readonly)

Returns the value of attribute optional.



16
17
18
# File 'lib/railsmith/base_service/association_definition.rb', line 16

def optional
  @optional
end

#service_classObject (readonly)

Returns the value of attribute service_class.



16
17
18
# File 'lib/railsmith/base_service/association_definition.rb', line 16

def service_class
  @service_class
end

#validateObject (readonly)

Returns the value of attribute validate.



16
17
18
# File 'lib/railsmith/base_service/association_definition.rb', line 16

def validate
  @validate
end

Instance Method Details

#async?Boolean

Returns true when this association should be written in a background job rather than inline inside the parent’s transaction.

Returns:

  • (Boolean)


39
40
41
# File 'lib/railsmith/base_service/association_definition.rb', line 39

def async?
  @async
end

#inferred_foreign_key(parent_model_class = nil) ⇒ Object

Returns the FK column name (Symbol) for this association. Falls back to auto-inference from the parent model class when no explicit foreign_key was given.

has_many / has_one: FK lives on the child → parent_model_id (e.g. order_id) belongs_to: FK lives on this record → association_name_id (e.g. customer_id)

Parameters:

  • parent_model_class (Class, nil) (defaults to: nil)

    the parent model class (used for inference)



51
52
53
54
55
56
57
58
59
60
# File 'lib/railsmith/base_service/association_definition.rb', line 51

def inferred_foreign_key(parent_model_class = nil)
  return @foreign_key if @foreign_key

  case kind
  when :has_many, :has_one
    :"#{underscore_model_name(parent_model_class)}_id"
  when :belongs_to
    :"#{name}_id"
  end
end