Module: Subroutine::AssociationFields

Extended by:
ActiveSupport::Concern
Defined in:
lib/subroutine/association_fields.rb,
lib/subroutine/association_fields/configuration.rb,
lib/subroutine/association_fields/component_configuration.rb,
lib/subroutine/association_fields/association_type_mismatch_error.rb

Defined Under Namespace

Modules: ClassMethods Classes: AssociationTypeMismatchError, ComponentConfiguration, Configuration

Instance Method Summary collapse

Instance Method Details

#clear_field_with_association(field_name) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
# File 'lib/subroutine/association_fields.rb', line 151

def clear_field_with_association(field_name)
  config = get_field_config(field_name)

  if config&.behavior == :association
    clear_field(config.foreign_type_method) if config.polymorphic?
    clear_field(config.foreign_key_method)
    association_cache.delete(config.field_name)
  else
    clear_field_without_association(field_name)
  end
end

#fetch_association_instance(_type, _fk, _unscoped = false) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/subroutine/association_fields.rb', line 179

def fetch_association_instance(_type, _fk, _unscoped = false)
  return nil unless _type && _fk

  klass = _type
  klass = klass.classify.constantize if klass.is_a?(String)

  return nil unless klass

  scope = klass.all
  scope = scope.unscoped if _unscoped

  scope.find(_fk)
end

#field_provided_with_association?(field_name) ⇒ Boolean

Returns:

  • (Boolean)


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/subroutine/association_fields.rb', line 163

def field_provided_with_association?(field_name)
  config = get_field_config(field_name)

  if config&.behavior == :association
    provided = true
    provided &&= field_provided?(config.foreign_type_method) if config.polymorphic?
    provided &&= field_provided?(config.foreign_key_method)
    provided
  elsif config&.behavior == :association_component
    field_provided_without_association?(field_name) ||
      field_provided_without_association?(config.association_name)
  else
    field_provided_without_association?(field_name)
  end
end

#get_field_with_association(field_name) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/subroutine/association_fields.rb', line 134

def get_field_with_association(field_name)
  config = get_field_config(field_name)

  if config&.behavior == :association
    stored_result = association_cache[config.field_name]
    return stored_result unless stored_result.nil?

    fk = config.field_reader? ? send(config.foreign_key_method) : get_field(config.foreign_id_method)
    type = config.field_reader? || !config.polymorphic? ? send(config.foreign_type_method) : get_field(config.foreign_type_method)

    result = fetch_association_instance(type, fk, config.unscoped?)
    association_cache[config.field_name] = result
  else
    get_field_without_association(field_name)
  end
end

#maybe_raise_on_association_type_mismatch!(config, record) ⇒ Object



193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/subroutine/association_fields.rb', line 193

def maybe_raise_on_association_type_mismatch!(config, record)
  return if config.polymorphic?
  return if record.nil?

  klass = config.inferred_class_name.constantize

  return if record.class <= klass || record.class >= klass

  message = "#{klass}(##{klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"

  errors.add(:base, message)
  raise Subroutine::AssociationFields::AssociationTypeMismatchError, self
end

#params_with_associationsObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/subroutine/association_fields.rb', line 97

def params_with_associations
  association_fields = field_configurations.select { |_name, config| config.behavior == :association }
  return params if association_fields.empty?

  excepts = []
  association_fields.each_pair do |_name, config|
    excepts << config.foreign_key_method
    excepts << config.foreign_type_method if config.polymorphic?
  end

  out = params.except(*excepts)
  association_fields.each_pair do |field_name, config|
    next unless field_provided?(field_name)

    out[field_name] = config.field_reader? ? send(field_name) : get_field(field_name)
  end

  out
end

#set_field_with_association(field_name, value, opts = {}) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/subroutine/association_fields.rb', line 117

def set_field_with_association(field_name, value, opts = {})
  config = get_field_config(field_name)

  if config&.behavior == :association
    maybe_raise_on_association_type_mismatch!(config, value)
    set_field(config.foreign_type_method, value&.class&.name, opts) if config.polymorphic?
    set_field(config.foreign_key_method, value&.id, opts)
    association_cache[config.field_name] = value
  else
    if config&.behavior == :association_component
      clear_field_without_association(config.association_name)
    end

    set_field_without_association(field_name, value, opts)
  end
end

#setup_fields_with_association(*args) ⇒ Object



92
93
94
95
# File 'lib/subroutine/association_fields.rb', line 92

def setup_fields_with_association(*args)
  @association_cache = {}
  setup_fields_without_association(*args)
end