diff --git a/db/migrate/20240304090449_migrate_interaction_settings_to_policy.rb b/db/migrate/20240304090449_migrate_interaction_settings_to_policy.rb index a0ce0a6638..ea4cfccdf9 100644 --- a/db/migrate/20240304090449_migrate_interaction_settings_to_policy.rb +++ b/db/migrate/20240304090449_migrate_interaction_settings_to_policy.rb @@ -4,46 +4,50 @@ class MigrateInteractionSettingsToPolicy < ActiveRecord::Migration[7.1] disable_ddl_transaction! # Dummy classes, to make migration possible across version changes - class Account < ApplicationRecord - has_one :user, inverse_of: :account - has_one :notification_policy, inverse_of: :account - end - class User < ApplicationRecord - belongs_to :account + belongs_to :notification_policy, foreign_key: 'account_id', primary_key: 'account_id', optional: true, inverse_of: false end - class NotificationPolicy < ApplicationRecord - belongs_to :account - end + class NotificationPolicy < ApplicationRecord; end def up - User.includes(account: :notification_policy).find_each do |user| - deserialized_settings = Oj.load(user.attributes_before_type_cast['settings']) + User.includes(:notification_policy).in_batches do |users| + NotificationPolicy.upsert_all(users.filter_map { |user| policy_for_user(user) }) + end + end - next if deserialized_settings.nil? + def down; end - policy = user.account.notification_policy || user.account.build_notification_policy - requires_new_policy = false + private - if deserialized_settings['interactions.must_be_follower'] - policy.filter_not_followers = true - requires_new_policy = true - end + def policy_for_user(user) + deserialized_settings = Oj.load(user.attributes_before_type_cast['settings']) + return if deserialized_settings.nil? - if deserialized_settings['interactions.must_be_following'] - policy.filter_not_following = true - requires_new_policy = true - end + requires_new_policy = false - unless deserialized_settings['interactions.must_be_following_dm'] - policy.filter_private_mentions = false - requires_new_policy = true - end + policy = { + account_id: user.account_id, + filter_not_followers: false, + filter_not_following: false, + filter_private_mentions: true, + } - policy.save if requires_new_policy && policy.changed? + if deserialized_settings['interactions.must_be_follower'] + policy[:filter_not_followers] = true + requires_new_policy = true end - end - def down; end + if deserialized_settings['interactions.must_be_following'] + policy[:filter_not_following] = true + requires_new_policy = true + end + + unless deserialized_settings['interactions.must_be_following_dm'] + policy[:filter_private_mentions] = false + requires_new_policy = true + end + + policy if requires_new_policy + end end diff --git a/db/post_migrate/20240321160706_migrate_interaction_settings_to_policy_again.rb b/db/post_migrate/20240321160706_migrate_interaction_settings_to_policy_again.rb index 9baefa6775..c789b63951 100644 --- a/db/post_migrate/20240321160706_migrate_interaction_settings_to_policy_again.rb +++ b/db/post_migrate/20240321160706_migrate_interaction_settings_to_policy_again.rb @@ -4,51 +4,51 @@ class MigrateInteractionSettingsToPolicyAgain < ActiveRecord::Migration[7.1] disable_ddl_transaction! # Dummy classes, to make migration possible across version changes - class Account < ApplicationRecord - has_one :user, inverse_of: :account - has_one :notification_policy, inverse_of: :account - end - class User < ApplicationRecord - belongs_to :account + belongs_to :notification_policy, foreign_key: 'account_id', primary_key: 'account_id', optional: true, inverse_of: false end - class NotificationPolicy < ApplicationRecord - belongs_to :account - end + class NotificationPolicy < ApplicationRecord; end def up - User.includes(account: :notification_policy).find_each do |user| - deserialized_settings = Oj.load(user.attributes_before_type_cast['settings']) + User.includes(:notification_policy).in_batches do |users| + NotificationPolicy.insert_all(users.filter_map { |user| policy_for_user(user) }) + end + end + + def down; end - next if deserialized_settings.nil? + private - # If the user has configured a notification policy, don't override it - next if user.account.notification_policy.present? + def policy_for_user(user) + deserialized_settings = Oj.load(user.attributes_before_type_cast['settings']) + return if deserialized_settings.nil? + return if user.notification_policy.present? - policy = user.account.build_notification_policy - requires_new_policy = false + requires_new_policy = false - if deserialized_settings['interactions.must_be_follower'] - policy.filter_not_followers = true - requires_new_policy = true - end + policy = { + account_id: user.account_id, + filter_not_followers: false, + filter_not_following: false, + filter_private_mentions: true, + } - if deserialized_settings['interactions.must_be_following'] - policy.filter_not_following = true - requires_new_policy = true - end + if deserialized_settings['interactions.must_be_follower'] + policy[:filter_not_followers] = true + requires_new_policy = true + end - unless deserialized_settings['interactions.must_be_following_dm'] - policy.filter_private_mentions = false - requires_new_policy = true - end + if deserialized_settings['interactions.must_be_following'] + policy[:filter_not_following] = true + requires_new_policy = true + end - policy.save if requires_new_policy && policy.changed? - rescue ActiveRecord::RecordNotUnique - next + unless deserialized_settings['interactions.must_be_following_dm'] + policy[:filter_private_mentions] = false + requires_new_policy = true end - end - def down; end + policy if requires_new_policy + end end