Module: RactorRailsShim::ActiveRecordAttributesPatch::InstanceMethods

Defined in:
lib/ractor_rails_shim/patches/active_model_attribute.rb

Instance Method Summary collapse

Instance Method Details

#_default_attributesObject

ActiveRecord overrides _default_attributes (attributes.rb:253) with a version that reads the @default_attributes class ivar and opens a connection to build the AttributeSet. Same per-Ractor fix as above: cache in IES so workers never read/write the shared class ivar.



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/ractor_rails_shim/patches/active_model_attribute.rb', line 135

def _default_attributes # :nodoc:
  key = :"rrs_default_attributes_#{object_id}"
  RactorRailsShim.storage[key] ||= begin
    attributes_hash = with_connection do |connection|
      columns_hash.transform_values do |column|
        ::ActiveModel::Attribute.from_database(
          column.name, column.default, type_for_column(connection, column)
        )
      end
    end
    attribute_set = ::ActiveModel::AttributeSet.new(attributes_hash)
    apply_pending_attribute_modifications(attribute_set)
    # ActiveStorage::Blob#metadata is declared via `store :metadata,
    # coder: ActiveRecord::Coders::JSON`, which registers a
    # Type::Serialized decorator via `decorate_attributes`. The
    # decorator is applied once (pending list is then empty), but this
    # per-worker rebuild from `columns_hash` uses the raw column type
    # (Type::Text), not the decorated Type::Serialized. Re-apply the
    # serialized type for :metadata so `read_attribute(:metadata)` and
    # store accessors (`identified=`, ...) work in worker Ractors.
    if defined?(::ActiveStorage::Blob) && self == ::ActiveStorage::Blob
      (attribute_set)
    end
    attribute_set
  end
end

#_rrs_apply_blob_metadata_type!(attribute_set) ⇒ Object

Apply Type::Serialized (with IndifferentCoder(JSON)) to the :metadata and "metadata" attributes in the given AttributeSet, so store accessors on ActiveStorage::Blob (e.g. identified=) persist.



165
166
167
168
169
170
171
172
173
174
# File 'lib/ractor_rails_shim/patches/active_model_attribute.rb', line 165

def (attribute_set)
  coder = ::ActiveRecord::Coders::JSON.new
  ind_coder = ::ActiveRecord::Store::IndifferentCoder.new(:metadata, coder)
  [:metadata, "metadata"].each do |key|
    attr = attribute_set[key]
    next unless attr && !attr.type.is_a?(::ActiveRecord::Type::Serialized)
    meta_type = ::ActiveRecord::Type::Serialized.new(attr.type, ind_coder)
    attribute_set[key] = attr.with_type(meta_type)
  end
end