Skip to content
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
13 changes: 8 additions & 5 deletions app/controllers/people_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,13 @@ def create
@person.email
)
if duplicates.any?
redirect_to check_duplicates_people_path(
first_name: @person.first_name,
last_name: @person.last_name,
email: @person.email
)
@first_name = @person.first_name
@last_name = @person.last_name
@email = @person.email
@duplicates = duplicates
@blocked = duplicates.any? { |d| d[:blocked] }
@stored_params = params[:person].to_unsafe_h
render :check_duplicates
return
end
end
Expand Down Expand Up @@ -162,6 +164,7 @@ def check_duplicates
@email = params[:email]
@duplicates = find_duplicate_people(@first_name, @last_name, @email)
@blocked = @duplicates.any? { |d| d[:blocked] }
@stored_params = {}
end

private
Expand Down
11 changes: 10 additions & 1 deletion app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,15 @@ def create
person_id = params[:person_id].presence || params.dig(:user, :person_id).presence || @user.person_id
duplicates = find_duplicate_users(email, exclude_person_id: person_id)
if duplicates.any?
redirect_to check_duplicates_users_path(email: email, person_id: person_id)
@email = email
@person_id = person_id
@duplicates = duplicates
@blocked = duplicates.any? { |d| d[:blocked] }
@stored_params = {
"user" => params[:user].to_unsafe_h,
"person_id" => params[:person_id].presence || params.dig(:user, :person_id).presence
}
render :check_duplicates
return
end
end
Expand Down Expand Up @@ -112,6 +120,7 @@ def check_duplicates
@person_id = params[:person_id]
@duplicates = find_duplicate_users(@email, exclude_person_id: @person_id)
@blocked = @duplicates.any? { |d| d[:blocked] }
@stored_params = {}
end

def update
Expand Down
25 changes: 25 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,29 @@ def us_time_zone_fundamentals
]
ActiveSupport::TimeZone.us_zones.select { |z| zone_names.include?(z.name) }.sort_by { |z| zone_names.index(z.name) }.map { |z| [ z.to_s, z.name ] }
end

def hidden_fields_for_params(params_hash, prefix = nil)
return "".html_safe if params_hash.blank?

fields = []
params_hash.each do |key, value|
field_name = prefix ? "#{prefix}[#{key}]" : key.to_s

if value.is_a?(Hash)
fields << hidden_fields_for_params(value, field_name)
elsif value.is_a?(Array)
value.each_with_index do |item, index|
if item.is_a?(Hash)
fields << hidden_fields_for_params(item, "#{field_name}[#{index}]")
else
fields << tag(:input, type: "hidden", name: "#{field_name}[]", value: item)
end
end
else
fields << tag(:input, type: "hidden", name: field_name, value: value)
end
end

safe_join(fields)
end
end
16 changes: 10 additions & 6 deletions app/views/people/check_duplicates.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,19 @@
<% end %>

<div class="flex gap-3 justify-center">
<%= link_to "Go back", "javascript:history.back()", class: "btn btn-secondary-outline" %>
<%= link_to "Go back", new_person_path(person: @stored_params), class: "btn btn-secondary-outline" %>

<% unless @blocked %>
<%= form_with url: people_path, method: :post, data: { turbo: false } do %>
<input type="hidden" name="person[first_name]" value="<%= @first_name %>">
<input type="hidden" name="person[last_name]" value="<%= @last_name %>">
<input type="hidden" name="person[email]" value="<%= @email %>">
<input type="hidden" name="person[created_by_id]" value="<%= current_user.id %>">
<input type="hidden" name="person[updated_by_id]" value="<%= current_user.id %>">
<% if @stored_params.present? %>
<%= hidden_fields_for_params(@stored_params, "person") %>
<% else %>
<input type="hidden" name="person[first_name]" value="<%= @first_name %>">
<input type="hidden" name="person[last_name]" value="<%= @last_name %>">
<input type="hidden" name="person[email]" value="<%= @email %>">
<input type="hidden" name="person[created_by_id]" value="<%= current_user.id %>">
<input type="hidden" name="person[updated_by_id]" value="<%= current_user.id %>">
<% end %>
<input type="hidden" name="skip_duplicate_check" value="1">
<button type="submit" class="btn btn-primary">Create anyway</button>
<% end %>
Expand Down
16 changes: 12 additions & 4 deletions app/views/users/check_duplicates.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,21 @@
<% end %>

<div class="flex gap-3 justify-center">
<%= link_to "Go back", "javascript:history.back()", class: "btn btn-secondary-outline" %>
<%= link_to "Go back", new_user_path(@stored_params), class: "btn btn-secondary-outline" %>

<% unless @blocked %>
<%= form_with url: users_path, method: :post, data: { turbo: false } do %>
<input type="hidden" name="user[email]" value="<%= @email %>">
<% if @person_id.present? %>
<input type="hidden" name="person_id" value="<%= @person_id %>">
<% if @stored_params.present? && @stored_params["user"].present? %>
<%= hidden_fields_for_params(@stored_params.fetch("user", {}), "user") %>
<% person_id_value = @stored_params["person_id"].presence || @person_id %>
<% if person_id_value.present? %>
<input type="hidden" name="person_id" value="<%= person_id_value %>">
<% end %>
<% else %>
<input type="hidden" name="user[email]" value="<%= @email %>">
<% if @person_id.present? %>
<input type="hidden" name="person_id" value="<%= @person_id %>">
<% end %>
<% end %>
<input type="hidden" name="skip_duplicate_check" value="1">
<button type="submit" class="btn btn-primary">Create anyway</button>
Expand Down
65 changes: 65 additions & 0 deletions spec/requests/people_create_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,71 @@
end
end

describe "duplicate check on create" do
let!(:existing_person) { create(:person, first_name: "Jane", last_name: "Doe", email: "jane.doe@example.com") }

it "renders check_duplicates when a duplicate is found" do
post people_path, params: {
person: {
first_name: "Jane",
last_name: "Doe",
email: "jane.new@testmail.org",
created_by_id: admin.id,
updated_by_id: admin.id
}
}

expect(response).to have_http_status(:ok)
expect(response.body).to include("Possible duplicate person")
expect(response.body).to include("Jane Doe")
end

it "does not create the person when duplicates are found" do
expect {
post people_path, params: {
person: {
first_name: "Jane",
last_name: "Doe",
email: "jane.new@testmail.org",
created_by_id: admin.id,
updated_by_id: admin.id
}
}
}.not_to change(Person, :count)
end

it "includes form params as hidden fields for Create anyway" do
post people_path, params: {
person: {
first_name: "Jane",
last_name: "Doe",
email: "jane.new@testmail.org",
email_2: "jane.alt@testmail.org",
created_by_id: admin.id,
updated_by_id: admin.id
}
}

expect(response.body).to include("jane.alt@testmail.org")
expect(response.body).to include("skip_duplicate_check")
end

it "creates the person when skip_duplicate_check is set" do
expect {
post people_path, params: {
skip_duplicate_check: "1",
person: {
first_name: "Jane",
last_name: "Doe",
email: "jane.new@testmail.org",
created_by_id: admin.id,
updated_by_id: admin.id
}
}
}.to change(Person, :count).by(1)
end
end

describe "user_attributes are applied on create" do
it "updates the user's time_zone from the person form" do
user = create(:user, time_zone: "Hawaii")
Expand Down
69 changes: 69 additions & 0 deletions spec/requests/users_create_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
require "rails_helper"

RSpec.describe "POST /users", type: :request do
let(:admin) { create(:user, :admin) }

before { sign_in admin }

describe "duplicate check on create" do
let!(:existing_person) do
Person.create!(
first_name: "Solo", last_name: "Person",
email: "solo@testmail.org",
created_by: admin, updated_by: admin
)
end

it "renders check_duplicates when a duplicate is found" do
post users_path, params: {
user: {
email: "solo@testmail.org",
first_name: "New",
last_name: "User"
}
}

expect(response).to have_http_status(:ok)
expect(response.body).to include("Possible duplicate user")
expect(response.body).to include("solo@testmail.org")
end

it "does not create the user when duplicates are found" do
expect {
post users_path, params: {
user: {
email: "solo@testmail.org",
first_name: "New",
last_name: "User"
}
}
}.not_to change(User, :count)
end

it "includes form params as hidden fields for Create anyway" do
post users_path, params: {
user: {
email: "solo@testmail.org",
first_name: "New",
last_name: "User"
}
}

expect(response.body).to include("solo@testmail.org")
expect(response.body).to include("skip_duplicate_check")
end

it "creates the user when skip_duplicate_check is set" do
expect {
post users_path, params: {
skip_duplicate_check: "1",
user: {
email: "solo@testmail.org",
first_name: "New",
last_name: "User"
}
}
}.to change(User, :count).by(1)
end
end
end