matewka
(matewka)
1
こんにちは、皆さん。
数週間前からこの問題で Google 検索を続けていますが、もう諦めそうになっています。
背景:
私はスポーツクラブ向けのマルチテナント管理パネルを開発・保守しています。
セルフホスト型の Discourse フォーラムは、現在それらのクラブのメンバーにのみ公開されています。これを一般公開したいと考えています。私の独自 SSO 統合により、ログイン時にデータベースからユーザーのフルネームが自動的に Discourse ユーザーに割り当てられます。
問題点:
現在、ユーザーのフルネームは同じクラブのメンバーにのみ表示されるべきであるため、フォーラムを一般公開することができません。
私は Ruby 開発の経験はゼロです(JS 開発者です)が、これまで以下のコード部分まで理解できました。
# plugin.rb
after_initialize {
require_dependency 'basic_user_serializer'
require_dependency 'current_user'
class ::BasicUserSerializer
attributes :name
def name
# クラブへの所属を示すグループ名の固定セット
clubGroups = Array['foo', 'bar', 'baz']
# 理解できない部分:
# 現在ログインしているユーザーの `clubGroups` のいずれかを共有している場合のみ、
# ユーザーの名前を表示する。
# 例:'bar' グループに所属するユーザーとしてログインしている場合、つまり Bar クラブに所属している場合、
# 'bar' グループに所属している他のユーザーの名前のみを表示できるはず。
???
end
end
}
以下のことが理解できていません:
- 現在のユーザーのグループを取得する方法
- 対象ユーザーのグループを取得する方法
これらが分かれば、2 つの配列を clubGroups と比較して、ユーザーの名前を表示するかどうかを判断できます。
もう一つの課題は、自分自身の名前を編集する機能を無効にすることですが、それはまた別の話です。
GroupUser モデルには、ユーザーのグループ所属情報が含まれています。
現在のユーザーのグループ ID を取得するには、以下のようにします:GroupUser.where(user_id: current_user.id)
これにより、Active Record リレーションが返されます。
その後、それを配列に変換するために map を使用できます:
GroupUser.where(user_id: myuser.id).map {|gu| gu.group_id}
注釈付きユーザーについても、同様のアプローチを採用してください。
matewka
(matewka)
3
完璧です!ありがとうございます 
まだそれを動作する解決策にどうすればいいかはわかりませんが、それはすでに大きなヒントです。
matewka
(matewka)
5
別の障害:
現在のユーザーの ID を取得してクエリに渡そうとする際、どのように取得すればよいのかわかりません。
コード内で CurrentUser モデルに移動すると、要件に関連していそうなメソッドは current_user しかありませんが、以下を実行するとエラーが発生します。
pp CurrentUser.current_user
エラーメッセージ:
undefined method `current_user' for CurrentUser:Module
Ruby に関する基本的な知識が不足しているのだと思いますが、もしかしたら簡単に解決できるかもしれませんでしょうか?
RGJ
(Richard - Communiteq)
6
このプラグインのコードをご覧になることをお勧めします。同じグループのメンバーにアバター装飾を追加し、グループメンバー同士が互いに認識できるようにする機能です。これは別の機能ですが、閲覧ユーザーが投稿ユーザーと同じグループに所属しているかを確認するコードが含まれています。
ヒントとなるのはこのメソッドです:
def user_is_current_user
object.id == scope.user&.id
end
シリアライズ対象のユーザーは object です。
現在のユーザーは実際には scope.user にあるため、以下のように記述すれば現在のユーザーに対して動作するはずです:
GroupUser.where(user_id: scope.user&.id).map {|gu| gu.group_id}
その他、いくつかのヒント:
- Discourse のソースコードを読む
- @RGJ が指摘している通り、いくつかのオープンソースプラグインを見て、実装方法を確認する
- Rails コンソールでプロトタイプを作成する(
rails c --sandbox)
matewka
(matewka)
8
素晴らしい!とても有益な情報ですね。皆さん、ありがとう 
早速取り組んでみます 
matewka
(matewka)
9
このトピックの将来の訪問者のために、私が導き出した最終的な解決策を共有します。
完璧でも最適化されていませんが、動作します!それが最初、そして最も重要なステップです 
after_initialize {
require_dependency 'basic_user_serializer'
class ::BasicUserSerializer
attributes :name
def name
if user_is_current_user
return _old_name_method
else
# TODO: このリストを編集可能にする
clubGroups = Array['...']
if scope.user
ownGroups = GroupUser.where(user_id: scope.user.id)
.map { |gu| gu.group_id }
.map { |group_id| Group.find_by(id: group_id) }
.filter { |group| clubGroups.include? group.name }
if ownGroups.length > 0
ownGroupsIds = ownGroups.map { |g| g.id }
if GroupUser.exists?(user_id: user.id, group_id: ownGroupsIds)
return _old_name_method
end
end
end
end
return ''
end
private def _old_name_method
return Hash === user ? user[:name] : user.try(:name)
end
end
}