ユーザー名(「ユーザーネーム」ではなく「名前」)をまとめて変更する方法はありますか?

当社のフォーラムには、外部 SSO プロバイダー(WordPress を介して)のアカウント作成時の設定方法により、名(ユーザー名ではなく、名前)が誤ってメールアドレスに設定されてしまったユーザーが数百名います。

各プロフィールに個別にアクセスして手動で変更するのではなく、the_name@example.com から the_name(つまり、‘@’ 以降をすべて切り取る)へと、これらの名をまとめて変更する比較的簡単な方法はありませんか?

Rails コンソールから実行できます。ただし、これはここで説明するよりも複雑です。特に、メールアドレスがユーザーレコードに保存されなくなったためです。予算がある場合は、Marketplace に投稿するか、直接お問い合わせください。

あるいは、実際のメールアドレスがどうあれ構わないのであれば…

以下のようなコードです。

users = User.where('username like', '%@%')

その後、ループ処理を行い、gsub を使って @ 以降の文字列をすべて削除します。これが、スマホからできる限界の対応策です。

@pfaffman さん、ご返信ありがとうございます。SQL は書けますが、Rails コンソールでの作業は少し苦手です。Discourse の Python コンソールに入るにはどうすればよいでしょうか :slightly_smiling_face:?

データエクスプローラーのように UPDATE クエリも実行できるツールがあれば便利だと思います(もちろん、潜在的に危険な面もあることは理解しています)。

セルフホストされた Docker 版 Discourse の実行中のデータベースに、Sequel Pro や同様のサードパーティ製 SQL ツールを接続する方法はありますか?

そうですね、でも Rails で行うとデータベースを壊してしまうリスクがぐっと減ります。例えば、Rails で作業すれば、違法なユーザー名を作成してしまったことに気づけますし(他のテーブルの更新が必要な場合も、Rails が自動でやってくれますが、SQL ではそうはいきません)。また、SQL ではそうした処理を自分で実装する必要があります。

cd /var/discourse
./launcher enter app
rails c

これで Rails のコンソールに入れます。

users=User.where("username like '%@%'")
users.each do |user|
  user.name.gsub!(/@(.*)/,"")
  puts "新しい名前: #{user.name}"
  # user.save
end

これでやりたいことが実現できるはずです。動作しそうだと思ったら、user.save のコメントアウトを外して試してみてください。

まずはバックアップを取ってくださいね。(できれば、ステージングサーバー上で試すのがおすすめです。)

コードをありがとうございます!

この Discourse インスタンス用のステージングサーバーは持っていませんが、バックアップを取得してから、明日の早朝にコードを実行します。その頃はトラフィックがほとんど(あるいは全く)ないはずなので、問題が発生した場合はすぐに復元できます。

@pfaffman さん、本当にありがとうございます。

puts が問題なければ、かなり安全だと思います。では!

@ で切り取っても、個人情報(メールアドレス)は「巨大な悪いインターネット」に対してほとんど露呈したままです(ほとんどの人が @gmail.com や他の主要プロバイダーを使っているため)。むしろ、ユーザー名と同じ値に設定する方が良いでしょう。

@lionel-rowe さん、ご指摘ありがとうございます。その通りですね。ただ、ユーザー名はすでに同じ値になっています(ユーザー名は、ユーザーのメールアドレスから「@」より前の部分を取り出して作成されています)。

恐ろしいことだ。

コードを少し修正し、動作させるために小さな手順を追加する必要がありました。以下が修正後のコードです。

users = User.where("name like '%@%'")

すると Rails コンソールがユーザーデータに対して「more」コマンドを起動して表示し始めたので、q で抜ける必要がありました。その後:

users.each do |user|
  user.name.gsub!(/@(.*)/,"")
  puts "新しい名前: #{user.name}"
  # user.save
end

Rails コンソールが新しい名前のリストを表示しました(正しい!)、そして再びユーザーの「more」表示に戻りました。再度 q で抜けます。

その後:

users.each do |user|
  user.name.gsub!(/@(.*)/,"")
  puts "新しい名前: #{user.name}"
  user.save
end

これでメールアドレス形式のユーザー名はなくなり、フォーラムのフロントエンドもすべて正常に表示されるようになりました。

@pfaffman さんの親切なサポートに改めて感謝します。