Skip to content

Commit fddd626

Browse files
authored
Allow Organization and Partner Profile edit when associated records have validation errors (#4737)
* Validate Partner email during update too (not just creation) * Update wording for partner profile's pick-up email validations Starts with lowercase, no . at end * Display errors in Partner when updating Partner Profile instead of failing silently * Display errors in Partner Profile when updating Organization instead of showing 500
1 parent 39bdd8e commit fddd626

File tree

6 files changed

+81
-6
lines changed

6 files changed

+81
-6
lines changed

app/models/partner.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ class Partner < ApplicationRecord
4848
validates :organization, presence: true
4949
validates :name, presence: true, uniqueness: { scope: :organization }
5050

51-
validates :email, presence: true, uniqueness: { case_sensitive: false },
52-
format: { with: URI::MailTo::EMAIL_REGEXP, on: :create }
51+
validates :email, presence: true, uniqueness: { case_sensitive: false }, format: { with: URI::MailTo::EMAIL_REGEXP }
5352

5453
validates :quota, numericality: { greater_than_or_equal_to: 0 }, allow_blank: true
5554

app/models/partners/profile.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,14 @@ def pick_up_email_addresses
158158

159159
emails = split_pick_up_emails
160160
if emails.size > 3
161-
errors.add(:pick_up_email, "There can't be more than three pick up email addresses.")
161+
errors.add(:pick_up_email, "can't have more than three email addresses")
162162
nil
163163
end
164164
if emails.uniq.size != emails.size
165-
errors.add(:pick_up_email, "There should not be repeated email addresses.")
165+
errors.add(:pick_up_email, "should not have repeated email addresses")
166166
end
167167
emails.each do |e|
168-
errors.add(:pick_up_email, "Invalid email address for '#{e}'.") unless e.match? URI::MailTo::EMAIL_REGEXP
168+
errors.add(:pick_up_email, "is invalid") unless e.match? URI::MailTo::EMAIL_REGEXP
169169
end
170170
end
171171
end

app/services/organization_update_service.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def update(organization, params)
3030
result = organization.update(org_params)
3131

3232
return false unless result
33-
update_partner_flags(organization)
33+
return false unless update_partner_flags(organization)
3434
true
3535
end
3636

@@ -46,6 +46,9 @@ def update_partner_flags(organization)
4646
next if organization.send(field)
4747
organization.partners.each do |partner|
4848
partner.profile.update!(field => organization.send(field))
49+
rescue ActiveRecord::RecordInvalid => e
50+
organization.errors.add(:base, "Profile for partner '#{e.record.partner.name}' had error(s) preventing the organization from being saved. #{e.message}")
51+
return false
4952
end
5053
end
5154
end

app/services/partner_profile_update_service.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ def call
1818
@profile.served_areas.destroy_all
1919
@profile.attributes = @profile_params
2020
@profile.save!(context: :edit)
21+
else
22+
@error = "Partner '#{@partner.name}' had error(s) preventing the profile from being updated: #{@partner.errors.full_messages.join(", ")}"
2123
end
2224
end
2325
end

spec/services/organization_update_service_spec.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,52 @@
8888
end
8989
end
9090
end
91+
92+
context "when partner is invalid" do
93+
let(:params) { {name: "New organization"} }
94+
95+
before do
96+
organization.update!(enable_individual_requests: false)
97+
# Want to have an invalid email on purpose
98+
# rubocop:disable Rails::SkipsModelValidations
99+
partner_one.update_columns(email: "not/an_email")
100+
# rubocop:enable Rails::SkipsModelValidations
101+
end
102+
103+
it "updates the organization and returns true" do
104+
expect(described_class.update(organization, params)).to eq(true)
105+
expect(organization.name).to eq("New organization")
106+
end
107+
end
108+
109+
context "when partner profile is invalid" do
110+
let(:profile) { partner_one.profile }
111+
let(:params) { {name: "New organization"} }
112+
113+
before do
114+
organization.update!(enable_individual_requests: false)
115+
# Want to have an invalid email on purpose
116+
# rubocop:disable Rails::SkipsModelValidations
117+
profile.update_columns(pick_up_email: "not/an/email")
118+
# rubocop:enable Rails::SkipsModelValidations
119+
end
120+
121+
it "returns false" do
122+
expect(described_class.update(organization, params)).to eq(false)
123+
end
124+
125+
it "adds an error message to the organization" do
126+
described_class.update(organization, params)
127+
expect(organization.errors.full_messages).to include(
128+
"Profile for partner '#{partner_one.name}' had error(s) preventing the organization from being saved. Validation failed: Pick up email is invalid"
129+
)
130+
end
131+
132+
it "updates the organization regardless" do # because updating the organization takes place before updating partner profiles
133+
described_class.update(organization, params)
134+
expect(organization.name).to eq("New organization")
135+
end
136+
end
91137
end
92138
end
93139

spec/services/partner_profile_update_service_spec.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
end
4444
end
4545
end
46+
4647
context "when served area client shares pre-exist" do
4748
let!(:original_served_area_1) { create(:partners_served_area, partner_profile: profile, county: county_1, client_share: 51) }
4849
let!(:original_served_area_2) { create(:partners_served_area, partner_profile: profile, county: county_2, client_share: 49) }
@@ -93,5 +94,29 @@
9394
end
9495
end
9596
end
97+
98+
context "when the partner has invalid attributes" do
99+
let(:partner) { profile.partner }
100+
101+
before do
102+
# Want to have an invalid email on purpose
103+
# rubocop:disable Rails::SkipsModelValidations
104+
partner.update_columns(email: "not/an_email")
105+
# rubocop:enable Rails::SkipsModelValidations
106+
end
107+
108+
it "returns failure" do
109+
result = PartnerProfileUpdateService.new(partner, partner_params, basic_correct_attributes).call
110+
expect(result.success?).to eq(false)
111+
expect(result.error.to_s).to include("Partner '#{partner.name}' had error(s) preventing the profile from being updated: Email is invalid")
112+
end
113+
114+
it "doesn't update the partner profile" do
115+
old_pick_up_email = profile.pick_up_email
116+
valid_profile_params = {pick_up_email: "[email protected] "}
117+
PartnerProfileUpdateService.new(profile.partner, partner_params, valid_profile_params).call
118+
expect(profile.pick_up_email).to eq(old_pick_up_email)
119+
end
120+
end
96121
end
97122
end

0 commit comments

Comments
 (0)