ملحق لعرض الاسم الكامل للمستخدمين من نفس المجموعة فقط

مرحبًا بالجميع،

لقد كنت أبحث عن مشكلتي عبر جوجل لعدة أسابيع بالفعل، وأنا على وشك الاستسلام.

الخلفية:
أقوم بتطوير وصيانة لوحة تحكم متعددة المستأجرين لناديات رياضية.
منتدى 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
}

لا أستطيع معرفة الأشياء التالية:

  1. كيفية جلب مجموعات المستخدم الحالي
  2. كيفية جلب مجموعات المستخدم المستهدف

بمجرد الحصول على ما سبق، يمكنني مقارنة المصفوفتين مع clubGroups واتخاذ قرار بشأن عرض اسم المستخدم أم لا.

التحدي الآخر بالنسبة لي سيكون إيقاف إمكانية تعديل اسمك الخاص، ولكن هذه قصة مختلفة.

إعجاب واحد (1)

يحتوي نموذج GroupUser على عضوية المجموعة حسب المستخدم.

تريد شيئًا مثل: GroupUser.where(user_id: current_user.id) لإرجاع معرفات المجموعة للمستخدم الحالي.

سيؤدي ذلك إلى إرجاع علاقة Active Record.

ثم قد ترغب في تحويلها إلى مصفوفة باستخدام map:

GroupUser.where(user_id: myuser.id).map {|gu| gu.group_id}

اتبع نفس النهج لمستخدمك المميز.

إعجاب واحد (1)

ممتاز! شكرًا لك :slight_smile:

لا أعرف بعد كيف أحوله إلى حل عملي، لكن هذا بالفعل تلميح كبير.

إعجاب واحد (1)

لا تستسلم أبداً. استمر في التقدم. :rocket:

إعجاب واحد (1)

عقبة أخرى:

عند محاولة جلب معرف المستخدم الحالي لتمريره إلى الاستعلام، لا أعرف حقًا كيف يمكنني جلبه.
عند التنقل إلى نموذج CurrentUser في الكود، الطريقة الوحيدة التي تبدو ذات صلة بمتطلباتي هي current_user، ولكن عندما أفعل هذا:

pp CurrentUser.current_user

يظهر لي الخطأ التالي:

undefined method `current_user' for CurrentUser:Module

أعتقد أنني بالتأكيد أفتقد بعض المعرفة الأساسية حول Ruby هنا، ولكن ربما يمكنك حلها لي بسهولة؟

قد ترغب في الاطلاع على كود هذا الملحق. فهو يضيف لمسة مميزة للصورة الرمزية للأشخاص المنتمين إلى نفس المجموعات، مما يمكنهم من التعرف على بعضهم البعض كأعضاء في المجموعة. هذا أمر مختلف، لكنه يتضمن الكود الذي يتحقق مما إذا كان المستخدم الذي يشاهد المنشور ينتمي إلى نفس المجموعة مثل المستخدم الذي نشره.

إعجاب واحد (1)

السر هنا يكمن في هذه الدالة:

  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}

من المرجح أن تعمل مع المستخدم الحالي.

إلخ.

نصائح جيدة:

  1. اقرأ كود مصدر Discourse
  2. وفقًا لـ @RGJ، اطلع على بعض الإضافات مفتوحة المصدر لمعرفة كيفية قيامهم بالأشياء
  3. قم بإنشاء نماذج أولية للأشياء في وحدة تحكم Rails باستخدام الأمر rails c --sandbox

رائع! الكثير من المعرفة القيمة. شكرًا لكم يا رفاق :heart_eyes:

أغوص فيه الآن :dealwithit:

إعجاب واحد (1)

من أجل زوار هذا الموضوع في المستقبل، إليك الحل النهائي الذي توصلت إليه.

الحل ليس مثالياً ولا محسّناً، لكنه يعمل! وهذه هي الخطوة الأولى والأهم :wink:

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
}
إعجابَين (2)