From b21f2110a563ae651381f7ba9180ede5e9fe7622 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 06:57:15 +0000 Subject: [PATCH 1/8] Move time_zone from User to Person model and views Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com> --- app/controllers/application_controller.rb | 2 +- app/controllers/people_controller.rb | 1 + app/controllers/users_controller.rb | 2 +- app/models/person.rb | 7 ++++ app/models/user.rb | 7 ---- app/views/people/_form.html.erb | 12 +++++++ app/views/users/_form.html.erb | 32 ++++++++++++++----- .../20260215070000_add_time_zone_to_people.rb | 7 ++++ ...001_copy_time_zone_from_users_to_people.rb | 17 ++++++++++ ...60215070002_remove_time_zone_from_users.rb | 7 ++++ 10 files changed, 77 insertions(+), 17 deletions(-) create mode 100644 db/migrate/20260215070000_add_time_zone_to_people.rb create mode 100644 db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb create mode 100644 db/migrate/20260215070002_remove_time_zone_from_users.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 878e793ad..e98921ea0 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -32,7 +32,7 @@ def after_sign_out_path_for(resource_or_scope) around_action :set_time_zone_from_user def set_time_zone_from_user - zone = ActiveSupport::TimeZone[current_user&.time_zone || "UTC"] + zone = ActiveSupport::TimeZone[current_user&.person&.time_zone || "UTC"] if zone Time.use_zone(zone) { yield } else diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 87a88984f..1625b0e69 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -295,6 +295,7 @@ def person_params :bio, :notes, :display_name_preference, :pronouns, + :time_zone, :profile_show_name_preference, :profile_is_searchable, :profile_show_pronouns, diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6d47ddc22..14e34f0c8 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -325,7 +325,7 @@ def find_duplicate_users(email, exclude_person_id: nil) def user_params params.require(:user).permit( - :email, :comment, :person_id, :inactive, :locked, :primary_address, :time_zone, :super_user, + :email, :comment, :person_id, :inactive, :locked, :primary_address, :super_user, ##### legacy to remove later :agency_id, :legacy, :legacy_id, :subscribecode, :avatar, :first_name, :last_name, # legacy to remove later diff --git a/app/models/person.rb b/app/models/person.rb index 90e43da50..10b65fe6f 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -42,6 +42,7 @@ class Person < ApplicationRecord validates :last_name, presence: true validates :email, format: { with: URI::MailTo::EMAIL_REGEXP, message: "must be a valid email address" }, allow_blank: true validates :email_2, format: { with: URI::MailTo::EMAIL_REGEXP, message: "must be a valid email address" }, allow_blank: true + validate :time_zone_must_be_valid, if: :time_zone_changed? validate :unique_name_and_email_combination CONTACT_TYPES = [ "work", "personal" ].freeze @@ -158,6 +159,12 @@ def strip_whitespace self.email_2 = email_2&.strip end + def time_zone_must_be_valid + return if ActiveSupport::TimeZone[time_zone] + + errors.add(:time_zone, "is not a valid time zone") + end + def unique_name_and_email_combination return unless first_name.present? && last_name.present? diff --git a/app/models/user.rb b/app/models/user.rb index adc9f1f6e..017868016 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -67,7 +67,6 @@ class User < ApplicationRecord # Validations validates :email, presence: true, uniqueness: { case_sensitive: false } - validate :time_zone_must_be_valid, if: :time_zone_changed? validate :person_id_must_be_present_if_previously_set, on: :update validates_associated :person, if: -> { person.present? } @@ -207,12 +206,6 @@ def strip_whitespace self.email = email&.strip end - def time_zone_must_be_valid - return if ActiveSupport::TimeZone[time_zone] - - errors.add(:time_zone, "is not a valid time zone") - end - def person_id_must_be_present_if_previously_set return unless person_id_was.present? return if person_id.present? diff --git a/app/views/people/_form.html.erb b/app/views/people/_form.html.erb index eff9a0c93..211a496ed 100644 --- a/app/views/people/_form.html.erb +++ b/app/views/people/_form.html.erb @@ -209,6 +209,18 @@ }, hint: "Maximum 250 characters" %> + +
+ <%= f.input :time_zone, + as: :select, + collection: us_time_zone_fundamentals, + selected: f.object.time_zone.presence || "Pacific Time (US & Canada)", + include_blank: false, + hint: "Event times and other dates will be shown in this timezone.", + input_html: { class: "w-full" }, + wrapper_html: { class: "w-full max-w-md" } %> +
+
Social media links: diff --git a/app/views/users/_form.html.erb b/app/views/users/_form.html.erb index 849a515cc..ad69407cc 100644 --- a/app/views/users/_form.html.erb +++ b/app/views/users/_form.html.erb @@ -136,14 +136,30 @@
- <%= f.input :time_zone, - as: :select, - collection: us_time_zone_fundamentals, - selected: f.object.time_zone.presence || "Pacific Time (US & Canada)", - include_blank: false, - hint: "Event times and other dates will be shown in this timezone.", - input_html: { class: "w-full" }, - wrapper_html: { class: "w-full max-w-md" } %> + <% if @person %> +
+ +
+
+ <%= @person.time_zone || "Pacific Time (US & Canada)" %> +
+
+

+ Edit on <%= link_to "person profile", edit_person_path(@person), class: "underline" %> +

+
+ <% else %> +
+ +

+ Not available (no person associated with this user) +

+
+ <% end %>
<% if f.object.persisted? %> diff --git a/db/migrate/20260215070000_add_time_zone_to_people.rb b/db/migrate/20260215070000_add_time_zone_to_people.rb new file mode 100644 index 000000000..be7f59216 --- /dev/null +++ b/db/migrate/20260215070000_add_time_zone_to_people.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddTimeZoneToPeople < ActiveRecord::Migration[8.1] + def change + add_column :people, :time_zone, :string, default: "Pacific Time (US & Canada)" + end +end diff --git a/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb b/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb new file mode 100644 index 000000000..2bb3b39e7 --- /dev/null +++ b/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class CopyTimeZoneFromUsersToPeople < ActiveRecord::Migration[8.1] + def up + # Copy time_zone from users to people where user has a person + execute <<-SQL + UPDATE people + INNER JOIN users ON users.person_id = people.id + SET people.time_zone = users.time_zone + WHERE users.time_zone IS NOT NULL + SQL + end + + def down + # No need to reverse this data migration + end +end diff --git a/db/migrate/20260215070002_remove_time_zone_from_users.rb b/db/migrate/20260215070002_remove_time_zone_from_users.rb new file mode 100644 index 000000000..91b2e5392 --- /dev/null +++ b/db/migrate/20260215070002_remove_time_zone_from_users.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class RemoveTimeZoneFromUsers < ActiveRecord::Migration[8.1] + def change + remove_column :users, :time_zone, :string + end +end From c1dae8d7bda140b923002e5ae9bdf0f42221d05e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 06:58:24 +0000 Subject: [PATCH 2/8] Update tests for time_zone migration to Person Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com> --- spec/models/person_spec.rb | 20 ++++++++++++++++++++ spec/requests/users_spec.rb | 7 ------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index 6a9a34fc8..dc9b9d805 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -47,6 +47,26 @@ it { should allow_value("").for(:email_2) } it { should_not allow_value("not-an-email").for(:email_2).with_message("must be a valid email address") } + describe "time_zone validation" do + let(:admin) { create(:user, :admin) } + + it "accepts valid time zones" do + person = build(:person, time_zone: "Pacific Time (US & Canada)", created_by: admin, updated_by: admin) + expect(person).to be_valid + end + + it "rejects invalid time zones" do + person = build(:person, time_zone: "Invalid/Zone", created_by: admin, updated_by: admin) + expect(person).not_to be_valid + expect(person.errors[:time_zone]).to include("is not a valid time zone") + end + + it "allows nil time zone" do + person = build(:person, time_zone: nil, created_by: admin, updated_by: admin) + expect(person).to be_valid + end + end + describe "unique_name_and_email_combination" do let(:admin) { create(:user, :admin) } diff --git a/spec/requests/users_spec.rb b/spec/requests/users_spec.rb index 40a5dedc1..1a269804b 100644 --- a/spec/requests/users_spec.rb +++ b/spec/requests/users_spec.rb @@ -228,13 +228,6 @@ patch user_url(user), params: { user: new_attributes } expect(response).to redirect_to(users_url) end - - it "permits and updates time_zone" do - user = User.create! valid_attributes - patch user_url(user), params: { user: { time_zone: "Eastern Time (US & Canada)" } } - user.reload - expect(user.time_zone).to eq("Eastern Time (US & Canada)") - end end context "with invalid parameters" do From 35e3e0600e5e2a6eadde388e267a5dcfc6d43926 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 06:59:48 +0000 Subject: [PATCH 3/8] Fix time_zone validation and make migration database-agnostic Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com> --- app/models/person.rb | 2 +- ...260215070001_copy_time_zone_from_users_to_people.rb | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/models/person.rb b/app/models/person.rb index 10b65fe6f..a65605997 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -160,7 +160,7 @@ def strip_whitespace end def time_zone_must_be_valid - return if ActiveSupport::TimeZone[time_zone] + return if time_zone.blank? || ActiveSupport::TimeZone[time_zone] errors.add(:time_zone, "is not a valid time zone") end diff --git a/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb b/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb index 2bb3b39e7..84ca5e4ad 100644 --- a/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb +++ b/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb @@ -3,12 +3,10 @@ class CopyTimeZoneFromUsersToPeople < ActiveRecord::Migration[8.1] def up # Copy time_zone from users to people where user has a person - execute <<-SQL - UPDATE people - INNER JOIN users ON users.person_id = people.id - SET people.time_zone = users.time_zone - WHERE users.time_zone IS NOT NULL - SQL + # Using ActiveRecord for database compatibility + User.where.not(person_id: nil).where.not(time_zone: nil).find_each do |user| + Person.where(id: user.person_id).update_all(time_zone: user.time_zone) + end end def down From 5880a17ed4a0d2453bf784bc35abeadc0f7a70d8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 07:00:28 +0000 Subject: [PATCH 4/8] Optimize data migration for better performance Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com> --- ...001_copy_time_zone_from_users_to_people.rb | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb b/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb index 84ca5e4ad..8a386b879 100644 --- a/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb +++ b/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb @@ -3,9 +3,23 @@ class CopyTimeZoneFromUsersToPeople < ActiveRecord::Migration[8.1] def up # Copy time_zone from users to people where user has a person - # Using ActiveRecord for database compatibility - User.where.not(person_id: nil).where.not(time_zone: nil).find_each do |user| - Person.where(id: user.person_id).update_all(time_zone: user.time_zone) + # Using raw SQL for efficiency while being database-agnostic + if ActiveRecord::Base.connection.adapter_name.downcase.include?("mysql") + execute <<-SQL.squish + UPDATE people + INNER JOIN users ON users.person_id = people.id + SET people.time_zone = users.time_zone + WHERE users.time_zone IS NOT NULL + SQL + else + # PostgreSQL syntax + execute <<-SQL.squish + UPDATE people + SET time_zone = users.time_zone + FROM users + WHERE users.person_id = people.id + AND users.time_zone IS NOT NULL + SQL end end From e88cc632e17532332735107113299018ae168b62 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 21:17:23 +0000 Subject: [PATCH 5/8] Use nested attributes for time_zone on person form instead of moving field Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com> --- app/controllers/application_controller.rb | 2 +- app/controllers/people_controller.rb | 4 +-- app/controllers/users_controller.rb | 2 +- app/models/person.rb | 7 ----- app/models/user.rb | 7 +++++ app/views/people/_form.html.erb | 24 ++++++++------- app/views/users/_form.html.erb | 30 ++++++++++--------- .../20260215070000_add_time_zone_to_people.rb | 7 ----- ...001_copy_time_zone_from_users_to_people.rb | 29 ------------------ ...60215070002_remove_time_zone_from_users.rb | 7 ----- spec/models/person_spec.rb | 20 ------------- spec/requests/users_spec.rb | 7 +++++ 12 files changed, 48 insertions(+), 98 deletions(-) delete mode 100644 db/migrate/20260215070000_add_time_zone_to_people.rb delete mode 100644 db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb delete mode 100644 db/migrate/20260215070002_remove_time_zone_from_users.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e98921ea0..878e793ad 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -32,7 +32,7 @@ def after_sign_out_path_for(resource_or_scope) around_action :set_time_zone_from_user def set_time_zone_from_user - zone = ActiveSupport::TimeZone[current_user&.person&.time_zone || "UTC"] + zone = ActiveSupport::TimeZone[current_user&.time_zone || "UTC"] if zone Time.use_zone(zone) { yield } else diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 1625b0e69..93dcf921a 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -295,7 +295,6 @@ def person_params :bio, :notes, :display_name_preference, :pronouns, - :time_zone, :profile_show_name_preference, :profile_is_searchable, :profile_show_pronouns, @@ -370,7 +369,8 @@ def person_params :city2, :state2, :zip2, - :notes + :notes, + :time_zone ], affiliations_attributes: [ :id, diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 14e34f0c8..6d47ddc22 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -325,7 +325,7 @@ def find_duplicate_users(email, exclude_person_id: nil) def user_params params.require(:user).permit( - :email, :comment, :person_id, :inactive, :locked, :primary_address, :super_user, + :email, :comment, :person_id, :inactive, :locked, :primary_address, :time_zone, :super_user, ##### legacy to remove later :agency_id, :legacy, :legacy_id, :subscribecode, :avatar, :first_name, :last_name, # legacy to remove later diff --git a/app/models/person.rb b/app/models/person.rb index a65605997..90e43da50 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -42,7 +42,6 @@ class Person < ApplicationRecord validates :last_name, presence: true validates :email, format: { with: URI::MailTo::EMAIL_REGEXP, message: "must be a valid email address" }, allow_blank: true validates :email_2, format: { with: URI::MailTo::EMAIL_REGEXP, message: "must be a valid email address" }, allow_blank: true - validate :time_zone_must_be_valid, if: :time_zone_changed? validate :unique_name_and_email_combination CONTACT_TYPES = [ "work", "personal" ].freeze @@ -159,12 +158,6 @@ def strip_whitespace self.email_2 = email_2&.strip end - def time_zone_must_be_valid - return if time_zone.blank? || ActiveSupport::TimeZone[time_zone] - - errors.add(:time_zone, "is not a valid time zone") - end - def unique_name_and_email_combination return unless first_name.present? && last_name.present? diff --git a/app/models/user.rb b/app/models/user.rb index 017868016..adc9f1f6e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -67,6 +67,7 @@ class User < ApplicationRecord # Validations validates :email, presence: true, uniqueness: { case_sensitive: false } + validate :time_zone_must_be_valid, if: :time_zone_changed? validate :person_id_must_be_present_if_previously_set, on: :update validates_associated :person, if: -> { person.present? } @@ -206,6 +207,12 @@ def strip_whitespace self.email = email&.strip end + def time_zone_must_be_valid + return if ActiveSupport::TimeZone[time_zone] + + errors.add(:time_zone, "is not a valid time zone") + end + def person_id_must_be_present_if_previously_set return unless person_id_was.present? return if person_id.present? diff --git a/app/views/people/_form.html.erb b/app/views/people/_form.html.erb index 211a496ed..a48ea0c20 100644 --- a/app/views/people/_form.html.erb +++ b/app/views/people/_form.html.erb @@ -210,16 +210,20 @@ hint: "Maximum 250 characters" %>
-
- <%= f.input :time_zone, - as: :select, - collection: us_time_zone_fundamentals, - selected: f.object.time_zone.presence || "Pacific Time (US & Canada)", - include_blank: false, - hint: "Event times and other dates will be shown in this timezone.", - input_html: { class: "w-full" }, - wrapper_html: { class: "w-full max-w-md" } %> -
+ <% if f.object.user %> + <%= f.fields_for :user do |user_form| %> +
+ <%= user_form.input :time_zone, + as: :select, + collection: us_time_zone_fundamentals, + selected: user_form.object.time_zone.presence || "Pacific Time (US & Canada)", + include_blank: false, + hint: "Event times and other dates will be shown in this timezone.", + input_html: { class: "w-full" }, + wrapper_html: { class: "w-full max-w-md" } %> +
+ <% end %> + <% end %>
diff --git a/app/views/users/_form.html.erb b/app/views/users/_form.html.erb index ad69407cc..385fbefc6 100644 --- a/app/views/users/_form.html.erb +++ b/app/views/users/_form.html.erb @@ -135,32 +135,34 @@
-
- <% if @person %> + <% if @person %> +
- <%= @person.time_zone || "Pacific Time (US & Canada)" %> + <%= f.object.time_zone || "Pacific Time (US & Canada)" %>

Edit on <%= link_to "person profile", edit_person_path(@person), class: "underline" %>

- <% else %> -
- -

- Not available (no person associated with this user) -

-
- <% end %> -
+
+ <% else %> +
+ <%= f.input :time_zone, + as: :select, + collection: us_time_zone_fundamentals, + selected: f.object.time_zone.presence || "Pacific Time (US & Canada)", + include_blank: false, + hint: "Event times and other dates will be shown in this timezone.", + input_html: { class: "w-full" }, + wrapper_html: { class: "w-full max-w-md" } %> +
+ <% end %> <% if f.object.persisted? %> diff --git a/db/migrate/20260215070000_add_time_zone_to_people.rb b/db/migrate/20260215070000_add_time_zone_to_people.rb deleted file mode 100644 index be7f59216..000000000 --- a/db/migrate/20260215070000_add_time_zone_to_people.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class AddTimeZoneToPeople < ActiveRecord::Migration[8.1] - def change - add_column :people, :time_zone, :string, default: "Pacific Time (US & Canada)" - end -end diff --git a/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb b/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb deleted file mode 100644 index 8a386b879..000000000 --- a/db/migrate/20260215070001_copy_time_zone_from_users_to_people.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -class CopyTimeZoneFromUsersToPeople < ActiveRecord::Migration[8.1] - def up - # Copy time_zone from users to people where user has a person - # Using raw SQL for efficiency while being database-agnostic - if ActiveRecord::Base.connection.adapter_name.downcase.include?("mysql") - execute <<-SQL.squish - UPDATE people - INNER JOIN users ON users.person_id = people.id - SET people.time_zone = users.time_zone - WHERE users.time_zone IS NOT NULL - SQL - else - # PostgreSQL syntax - execute <<-SQL.squish - UPDATE people - SET time_zone = users.time_zone - FROM users - WHERE users.person_id = people.id - AND users.time_zone IS NOT NULL - SQL - end - end - - def down - # No need to reverse this data migration - end -end diff --git a/db/migrate/20260215070002_remove_time_zone_from_users.rb b/db/migrate/20260215070002_remove_time_zone_from_users.rb deleted file mode 100644 index 91b2e5392..000000000 --- a/db/migrate/20260215070002_remove_time_zone_from_users.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class RemoveTimeZoneFromUsers < ActiveRecord::Migration[8.1] - def change - remove_column :users, :time_zone, :string - end -end diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index dc9b9d805..6a9a34fc8 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -47,26 +47,6 @@ it { should allow_value("").for(:email_2) } it { should_not allow_value("not-an-email").for(:email_2).with_message("must be a valid email address") } - describe "time_zone validation" do - let(:admin) { create(:user, :admin) } - - it "accepts valid time zones" do - person = build(:person, time_zone: "Pacific Time (US & Canada)", created_by: admin, updated_by: admin) - expect(person).to be_valid - end - - it "rejects invalid time zones" do - person = build(:person, time_zone: "Invalid/Zone", created_by: admin, updated_by: admin) - expect(person).not_to be_valid - expect(person.errors[:time_zone]).to include("is not a valid time zone") - end - - it "allows nil time zone" do - person = build(:person, time_zone: nil, created_by: admin, updated_by: admin) - expect(person).to be_valid - end - end - describe "unique_name_and_email_combination" do let(:admin) { create(:user, :admin) } diff --git a/spec/requests/users_spec.rb b/spec/requests/users_spec.rb index 1a269804b..40a5dedc1 100644 --- a/spec/requests/users_spec.rb +++ b/spec/requests/users_spec.rb @@ -228,6 +228,13 @@ patch user_url(user), params: { user: new_attributes } expect(response).to redirect_to(users_url) end + + it "permits and updates time_zone" do + user = User.create! valid_attributes + patch user_url(user), params: { user: { time_zone: "Eastern Time (US & Canada)" } } + user.reload + expect(user.time_zone).to eq("Eastern Time (US & Canada)") + end end context "with invalid parameters" do From d77eec06b78f07dd7024d7e9e13b0a4b7970564a Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 16 Feb 2026 17:54:50 -0500 Subject: [PATCH 6/8] More explicitly handle user params sent over (e.g. timezone) when going from user to person create --- app/controllers/people_controller.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 93dcf921a..997a3a457 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -90,6 +90,9 @@ def create authorize! @person @person.user ||= User.find_by(id: params[:user_id]) if params[:user_id].present? @person.user ||= User.find_by(id: params.dig(:person, :user_attributes, :id)) if params.dig(:person, :user_attributes, :id).present? + if @person.user && person_params[:user_attributes].present? + @person.user.assign_attributes(person_params[:user_attributes].except(:id)) + end unless params[:skip_duplicate_check].present? duplicates = find_duplicate_people( From be870bc7ae7ebb4d81a76bf6973caa1e5c87066d Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 16 Feb 2026 17:55:34 -0500 Subject: [PATCH 7/8] Add spec for this flow --- spec/requests/people_create_spec.rb | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 spec/requests/people_create_spec.rb diff --git a/spec/requests/people_create_spec.rb b/spec/requests/people_create_spec.rb new file mode 100644 index 000000000..6ac5b5b41 --- /dev/null +++ b/spec/requests/people_create_spec.rb @@ -0,0 +1,31 @@ +require "rails_helper" + +RSpec.describe "POST /people", type: :request do + let(:admin) { create(:user, :admin) } + + before { sign_in admin } + + 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") + + post people_path, params: { + skip_duplicate_check: "1", + person: { + first_name: user.first_name, + last_name: user.last_name, + email: user.email, + created_by_id: admin.id, + updated_by_id: admin.id, + user_attributes: { + id: user.id, + time_zone: "Eastern Time (US & Canada)" + } + } + } + + expect(response).to redirect_to(Person.last) + expect(user.reload.time_zone).to eq("Eastern Time (US & Canada)") + end + end +end From ef5d001d9430b1d49507bd52b4e71cfe15425913 Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 16 Feb 2026 18:05:24 -0500 Subject: [PATCH 8/8] Assign user if not already on new --- app/controllers/people_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 997a3a457..2dcc7da3d 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -67,6 +67,7 @@ def show def new set_user @person = @user ? PersonFromUserService.new(user: @user).call : Person.new + @person.user = @user if @user authorize! @person set_form_variables end