ruby-on-railsrubyactiverecord

Rails: Active Record Validation for has_one


I have 2 models

class A < ApplicationRecord
 has_one :b, dependent: :destroy
 has_one :c, dependent: :destroy
end

and

class B < ApplicationRecord
  belongs_to :a
  validates :ip_address, presence_true, format : {with: regex,message:"must be valid"}
end

While saving / updating above records,

transaction do
  save_b(params)
  save_c(params)
 rescue ActiveRecord::RecordNotSaved => e
   handle_error
 rescue ActiveRecord::RecordInvalid => e
   handle_error
end

save_b(params)
 self.b ||= build_b(params)
 b.update!(params)
end

If invalid ip_address is sent in params, above code rescues in ActiveRecord::RecordNotSaved block. How can I refactor so that error rescues in ActiveRecord::RecordInvalid and I get error message defined for ip_address in model B


Solution

  • As everyone said above, when the update! method is called on b, if the validation fails, it doesn't throw ActiveRecord::RecordInvalid directly but rather bubbles up as ActiveRecord::RecordNotSaved.

    So, I suggest the following logic:

    class A < ApplicationRecord
      has_one :b, dependent: :destroy
      has_one :c, dependent: :destroy
    
      def save_b(params)
        self.b ||= build_b
        b.assign_attributes(params)
        
        if b.valid?
          b.save!
        else
          raise ActiveRecord::RecordInvalid.new(b)
        end
      end
    end
    

    By this way, validates the b record by using valid? and in case validation fails, it will throw ActiveRecord::RecordInvalid