I created a model with associations. But when I add more than 46 records to the association, the main model can no longer be saved - it fails with
PG::NotNullViolation: ERROR: null value in column "connect_id" violates not-null constraint
I finally figured that with more than 46 records Rails starts to write the transaction in two passes, leaving the foreign_keys empty (Null) in the first step and then later during the transaction an update does fill them in.
But, for this to work we would need deferred triggers, and Rails does not create deferrable triggers, at least not by default. (One could certainly fix that one.)
Since the foreign keys in my associations can be resolved (they are no circulars), I was wondering why Rails would do this properly with 46 records, but no longer with 47 records.
And after some search I found it in the code - and changed it:
module ActiveRecord
module AutosaveAssociation
module ClassMethods
private
def define_non_cyclic_method(name, &block)
return if method_defined?(name)
define_method(name) do |*args|
result = true; @_already_called ||= {}
# Loop prevention for validation of associations
@_already_called[name] ||= 0
unless @_already_called[name] >= 3
begin
@_already_called[name] += 1
result = instance_eval(&block)
ensure
@_already_called[name] = 0
end
end
result
end
end
end
end
end
By default this works with a boolean, i.e. there is only one cyclic loop allowed. This is clearly not enough. OTOH at some point there are stack overflows in ruby, so it is not clear what exactly is the proper value. For now I have it running with 3, and that seems work for my usecases.