Module: RactorRailsShim::ReflectionAssociationPatch
- Includes:
- ReflectionMemoPatch
- Defined in:
- lib/ractor_rails_shim/patches/activerecord_reflection.rb
Instance Method Summary collapse
- #active_record_primary_key ⇒ Object
- #association_foreign_key ⇒ Object
- #association_primary_key(klass = nil) ⇒ Object
-
#check_validity! ⇒ Object
check_validity! memoizes @validated by writing it on the (frozen, shared) reflection — which raises FrozenError in a worker Ractor.
- #foreign_key(infer_from_inverse_of: true) ⇒ Object
-
#inverse_name ⇒ Object
inverse_name writes @inverse_name on the frozen, shared reflection in a worker Ractor (Rails only sets it lazily, so it is genuinely undefined on a frozen object -> FrozenError).
- #join_table ⇒ Object
Methods included from ReflectionMemoPatch
Instance Method Details
#active_record_primary_key ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/ractor_rails_shim/patches/activerecord_reflection.rb', line 153 def active_record_primary_key custom_primary_key = [:primary_key] rrs_refl_cache[[object_id, :active_record_primary_key]] ||= if custom_primary_key if custom_primary_key.is_a?(Array) custom_primary_key.map { |pk| pk.to_s.freeze }.freeze else custom_primary_key.to_s.freeze end elsif active_record.has_query_constraints? || [:query_constraints] active_record.query_constraints_list elsif active_record.composite_primary_key? primary_key = primary_key(active_record) primary_key.include?("id") ? "id" : primary_key.freeze else primary_key(active_record).freeze end end |
#association_foreign_key ⇒ Object
149 150 151 |
# File 'lib/ractor_rails_shim/patches/activerecord_reflection.rb', line 149 def association_foreign_key rrs_refl_cache[[object_id, :association_foreign_key]] ||= -([:association_foreign_key]&.to_s || class_name.foreign_key) end |
#association_primary_key(klass = nil) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/ractor_rails_shim/patches/activerecord_reflection.rb', line 172 def association_primary_key(klass = nil) if primary_key = [:primary_key] rrs_refl_cache[[object_id, :association_primary_key, klass]] ||= if primary_key.is_a?(Array) primary_key.map { |pk| pk.to_s.freeze }.freeze else -primary_key.to_s end elsif (klass || self.klass).has_query_constraints? || [:query_constraints] rrs_refl_cache[[object_id, :association_primary_key, klass]] ||= -Array(active_record.query_constraints_list).first.to_s elsif active_record.composite_primary_key? rrs_refl_cache[[object_id, :association_primary_key, klass]] ||= primary_key(klass || self.klass) else rrs_refl_cache[[object_id, :association_primary_key, klass]] ||= primary_key(klass || self.klass).to_s end end |
#check_validity! ⇒ Object
check_validity! memoizes @validated by writing it on the (frozen, shared) reflection — which raises FrozenError in a worker Ractor. Reimplement it to store the validated flag in the per-worker cache instead. The body mirrors Rails' (minus the @validated write) and only reads via the other patched (cache-backed) reflection accessors, so it performs no ivar writes on the frozen object.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/ractor_rails_shim/patches/activerecord_reflection.rb', line 93 def check_validity! cache = rrs_refl_cache return if cache[[object_id, :validated]] check_validity_of_inverse! if !polymorphic? && (klass.composite_primary_key? || active_record.composite_primary_key?) if (has_one? || collection?) && Array(active_record_primary_key).length != Array(foreign_key).length raise ::ActiveRecord::Reflection::CompositePrimaryKeyMismatchError.new(self) elsif belongs_to? && Array(association_primary_key).length != Array(foreign_key).length raise ::ActiveRecord::Reflection::CompositePrimaryKeyMismatchError.new(self) end end cache[[object_id, :validated]] = true end |
#foreign_key(infer_from_inverse_of: true) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/ractor_rails_shim/patches/activerecord_reflection.rb', line 123 def foreign_key(infer_from_inverse_of: true) rrs_refl_cache[[object_id, :foreign_key, infer_from_inverse_of]] ||= if [:foreign_key] if [:foreign_key].is_a?(Array) [:foreign_key].map { |fk| -fk.to_s.freeze }.freeze else [:foreign_key].to_s.freeze end elsif [:query_constraints] [:query_constraints].map { |fk| -fk.to_s.freeze }.freeze else derived_fk = derive_foreign_key(infer_from_inverse_of: infer_from_inverse_of) if active_record.has_query_constraints? derived_fk = derive_fk_query_constraints(derived_fk) end if derived_fk.is_a?(Array) derived_fk.map! { |fk| -fk.freeze } derived_fk.freeze else -derived_fk.freeze end end end |
#inverse_name ⇒ Object
inverse_name writes @inverse_name on the frozen, shared reflection in a worker Ractor (Rails only sets it lazily, so it is genuinely undefined on a frozen object -> FrozenError). Cache it per-worker instead. Defined here (not on AbstractReflection) because the original inverse_name lives on AssociationReflection and would shadow an AbstractReflection-level override.
115 116 117 |
# File 'lib/ractor_rails_shim/patches/activerecord_reflection.rb', line 115 def inverse_name rrs_refl_cache[[object_id, :inverse_name]] ||= (.fetch(:inverse_of) { automatic_inverse_of }) end |
#join_table ⇒ Object
119 120 121 |
# File 'lib/ractor_rails_shim/patches/activerecord_reflection.rb', line 119 def join_table rrs_refl_cache[[object_id, :join_table]] ||= -([:join_table]&.to_s || derive_join_table) end |