Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MONGOID-5694 Fix validations on associations - DO NOT MERGE #5742

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions lib/mongoid/persistable/updatable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,16 @@ def update_attribute(name, value)
#
# @return [ true | false ] True if validation passed, false if not.
def update(attributes = {})
assign_attributes(attributes)
save
self.class.with_session do |session|
session.with_transaction do
assign_attributes(attributes)
save.tap do |result|
session.abort_transaction unless result
end
end
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work on versions of MongoDB which don't support transactions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it doesn't. It also does not work on standalones, which is a supported topology by Mongoid. I am just looking for possible solutions in this draft; it won't be merged.

rescue StandardError => e
false
end
alias :update_attributes :update

Expand Down
41 changes: 41 additions & 0 deletions spec/integration/validations_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# rubocop:todo all
# frozen_string_literal: true

require 'spec_helper'
require_relative './validations_spec_models'

describe 'validations' do

context 'when validating presence of has_and_belongs_to_many association' do
let(:company) { ValidationsSpecModels::Company.create! }
let(:client) { ValidationsSpecModels::Client.create!(companies: [company]) }

context 'when updating the association' do
it 'raises an error' do
expect { client.update!(companies: []) }.to raise_error(Mongoid::Errors::Validations)
end

it 'does not persist the changes' do
client.update!(companies: []) rescue nil
expect(client.reload.companies).not_to be_empty
end
end
end


context 'when validating presence of has_many association' do
let(:apartment) { ValidationsSpecModels::Apartment.create! }
let(:building) { ValidationsSpecModels::Building.create!(apartments: [apartment]) }

context 'when updating the association' do
it 'raises an error' do
expect { building.update!(apartments: []) }.to raise_error(Mongoid::Errors::Validations)
end

it 'does not persist the changes' do
building.update!(apartments: []) rescue nil
expect(building.reload.apartments).not_to be_empty
end
end
end
end
25 changes: 25 additions & 0 deletions spec/integration/validations_spec_models.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

module ValidationsSpecModels
class Company
include Mongoid::Document
end

class Client
include Mongoid::Document

has_and_belongs_to_many :companies, class_name: 'ValidationsSpecModels::Company'
validates :companies, presence: true
end

class Building
include Mongoid::Document
has_many :apartments, class_name: 'ValidationsSpecModels::Apartment'
validates :apartments, presence: true
end

class Apartment
include Mongoid::Document
belongs_to :building, class_name: 'ValidationsSpecModels::Building'
end
end
Loading