استخدام tag-chooser في إضافة

أعمل على إضافة (plugin) ستقوم بتعيين وسم افتراضي للمواضيع الجديدة التي تُنشأ في فئة معينة.

الكود أدناه “يعمل” إذا أدخلت أسماء الوسوم مفصولة بـ “|”، لذا فإن “tag1|tag2” تعمل. (كاد أن يكون ذلك غير معقول! لكنني أشتت الانتباه.)

<h3>{{i18n 'topic_default_tag.title'}}</h3>
<section class='field default-tag'>
  <div class="default-tag">
  <label>
    {{input type="list" value=category.custom_fields.default_tag }}
    {{popup-input-tip validation=tagValidation}}
    {{i18n 'topic_default_tag.default_tag'}}
  </label>
  </div>
</section>

ما أريده الآن هو وجود مُختار وسوم (tag selector) مناسب بدلاً من سلسلة غير مُتحقق منها. يبدو أن الكود التالي يجب أن يعمل:

<h3>{{i18n 'topic_default_tag.title'}}</h3>
<section class='field default-tag'>
  <div class="default-tag">
  <label>
    {{tag-chooser tags=category.custom_fields.default_tag tabindex="4" categoryId=category.id}}
    {{popup-input-tip validation=tagValidation}}
    {{i18n 'topic_default_tag.default_tag'}}
  </label>
  </div>
</section>

لكنه لا يعمل. جوهر مشكلتي هو أنني لا أملك أي فكرة تقريبًا عن سحر هاندلباردز (Handlebars) الذي يعمل هنا. مثلًا، أفترض أن القسم الأول يعمل لأنه يستخرج اسم الحقل سحرًا من default-tag في <section class='field default-tag'>، لكن ذلك كان مجرد حظ. :slight_smile:

عند استخدام tag-chooser، يتم تمرير الوسوم إلى Rails كمصفوفة، ثم يتم تجاهلها قبل أن أتمكن من تحويلها إلى سلسلة مفصولة بـ | لإدراجها في CategoryCustomField. أما مع {{input type=list...}}، فيمكنني إدخال السلسلة المفصولة بـ | بنفسي ويعمل كل شيء على ما يرام. هل أحتاج إلى نوع من سحر Ember لتحويل المصفوفة إلى سلسلة على جانب Ember؟

ربما أحتاج إلى فعل شيء مشابه لـ https://meta.discourse.org/t/whats-the-best-approach-to-access-category-specific-settings/40728؟

تعديل: لإضافة الوسوم قبل استدعاء الويب هوك (webhook)، استخدم after_create بدلاً من DiscourseEvent.on(:post_created). Rails أصبحت مفهومة لي إلى حد كبير الآن، لكن Ember وJavascript وCSS لا تزال غير واضحة بالنسبة لي.

يمكنك التحقق مما إذا كانت المتغيرات التي تستخدمها تحتوي على القيم المطلوبة عن طريق استخدام {{log variable_name}} والتحقق من وحدة التحكم. إذا لم يتم تمرير القيم الصحيحة إلى المكون، فلن يعرض الإخراج الصحيح.

يمكنك التحقق منها عن طريق القيام بنفس الأمر في الكود الأساسي للتأكد من صحة تمرير القيم.

أعتذر إذا بدا ذلك ساذجًا بالنسبة لك.

لا! أنا مجرد إنسان بدائي.

هذا مفيد جدًا، إذ لم أكن أعرف كيف أفعل ذلك. اتضح أن لدي حقًا بيانات في هذه الحقول. وبيانات اسم الوسم موجودة في category.custom_fields.default_tag ويتم تمريرها إلى mini-tag-chooser. يحتوي category.id على معرف الفئة، لكن المختار لا يعرض أي أوسمة.

لا أستطيع تحديد ما إذا كانت هذه البيانات ستُدرج في الحقل.

تعديل: أوه! لكن استخدام tag-chooser بدلاً من mini-tag-chooser يعمل كما ينبغي (سأقوم بتعديل الكود أعلاه وفقًا لذلك). المشكلة الوحيدة هي أن البيانات لا تُحفظ عند النقر على حفظ.

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

حسنًا، على جانب Rails، الأمر عبارة عن سلسلة مفصولة بـ |، وأرى بعد إرسالي أن البيانات التي أدخلتها يتم إرسالها، على سبيل المثال: "custom_fields"=>{"de fault_tag"=>["error", "high-availability", "best-practices"]}, و "custom_fields"=>{"de fault_tag"=>["health-checks"]},

إليك الأمر كاملاً:

Started PUT "/categories/2" for 127.0.0.1 at 2019-08-01 13:56:13 -0700
Processing by CategoriesController#update as */*
  Parameters: {"name"=>"Lounge", "slug"=>"lounge", "color"=>"EEEEEE", "text_color"=>"652D90", "permissions"=>{"trus
t_level_3"=>"1"}, "auto_close_hours"=>"", "auto_close_based_on_last_post"=>"false", "position"=>"3", "email_in"=>""
, "email_in_allow_strangers"=>"false", "mailinglist_mirror"=>"false", "allow_badges"=>"true", "custom_fields"=>{"de
fault_tag"=>["error", "high-availability", "best-practices"]}, "topic_template"=>"", "suppress_from_latest"=>"false
", "all_topics_wiki"=>"false", "allow_global_tags"=>"false", "sort_order"=>"", "sort_ascending"=>"", "topic_feature
d_link_allowed"=>"true", "show_subcategory_list"=>"false", "num_featured_topics"=>"3", "default_view"=>"", "subcate
gory_list_style"=>"rows_with_featured_topics", "default_top_period"=>"all", "minimum_required_tags"=>"0", "navigate
_to_first_post_after_read"=>"false", "search_priority"=>"0", "id"=>"2"}

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

شكرًا جزيلاً، @fzngagan!

تحرير: هُمم. أعتقد أن المشكلة هي:

Unpermitted parameter: :default_tag

ستستمتع حقًا بإيجاد الإجابة على ذلك. ومع ذلك، إذا كنت بحاجة إلى مساعدة، فسأكون سعيدًا جدًا بتقديمها. :slight_smile:

نعم، هذا صحيح. لا يعرف Rails حتى الآن كيفية التعامل مع هذا الحقل الجديد. تحتاج إلى إضافته إلى السيرياليزر (add_to_serializer) للحقل الجديد. يمكنك رؤية أمثلة على ذلك في الإضافات التي تضيف حقولًا مخصصة.

حسنًا، يتضمن plugin.rb ما يلي:

  Category.register_custom_field_type('default_tag', :list)
  Site.preloaded_category_custom_fields << 'default_tag' if Site.respond_to? :preloaded_category_custom_fields
  add_to_serializer(:basic_category, :default_tag) { object.custom_fields["default_tag"] }

المشروع متوفر على GitHub - pfaffman/discourse-topic-default-tag: Allow topics to include default tags · GitHub إذا أردت الاطلاع عليه.

أنا مرتبك لأن استخدام

   {{input type="list" value=category.custom_fields.default_tag }}

يعمل بشكل صحيح، بينما

{{tag-chooser tags=category.custom_fields.default_tag tabindex="4" categoryId=category.id}}

لا يعمل.

تحرير: يبدو أن استخدام tag-chooser يؤدي إلى إرسال حقل التخصيص الخاص بي إلى Rails كمصفوفة، ثم يتم تجاهله قبل معالجته. أما عند استخدام حقل نصي حيث أنشئ سلسلة مفصولة بـ |، فإن الأمر يعمل بشكل ممتاز. (ظننت أنني قد أصلح المشكلة باستخدام before_validation على جانب Rails، لكن دون جدوى.)

لذا، أعتقد أنني أحتاج إلى بعض السحر على جانب Ember لتحويل المصفوفة إلى سلسلة نصية قبل إعادتها.

أنا أيضاً استخدمت tag-chooser بدون معاملات، وقد جلب جميع الوسوم المتاحة.

بالإضافة إلى ذلك، أعتقد أنني وجدت السبب في عدم حفظ تلك الوسوم (أو حتى وصولها) :wink: على جانب Rails عند استخدام tag-chooser. عندما تستخدم input type list وتضيف حقل value، فإنه يصبح تلقائياً جزءاً من النموذج.

لكن الشفرة المُنشأة بواسطة tag chooser هي div. وهذا هو السبب في عدم إضافتها إلى إرسال النموذج.

أحاول وضع حل بديل لذلك. سأقدم طلب سحب (PR) بمجرد أن أتمكن من جعله يعمل.

تحدثت مع @j.jaffeux أمس وهو يعمل على إجراء تغيير.

هذا بالضبط ما أعمل عليه.

هذا رائع. بصفتي جديدًا، أحاول تعلم المزيد والمزيد، وهذا يساعد كثيرًا :slight_smile:

مرحبًا @pfaffman.

تمكّنت من إعداد إصلاح. لم أتمكن من تنفيذه من جانب Ember لأن tag-chooser بدا رائعًا جدًا للتخلي عنه، لكنني تمكّنت من ذلك من جانب Rails.

لقد كتبت دالة بسيطة في CategoriesController وسمّيتها :before_action، وفيها قمت بتحويل مصفوفة default_tag إلى سلسلة مفصولة بـ |.

ثانيًا، غيّرت before_update إلى before_commit لأن custom_fields تبدو محددة في تلك النقطة من التنفيذ.

هه، ظننت أنني جربت ذلك، لكنني سأتحقق من الأمر عندما أصل إلى المكتب. شكرًا لك!

أها! هذا هو الشيء الذي لا أعرف كيفية فعله. هل تضع ذلك في plugin.rb؟

نعم، هذا الحل نجح معي.

class ::ApplicationController
    def convert_default_tag
      return unless :topic_default_tag_enabled
      puts 'request'
     #فقط تحقق من وجود الحقل لتجنب الوقوع في أخطاء
      request.params["custom_fields"]["default_tag"] = request.params["custom_fields"]["default_tag"].join('|')
      p request.params["custom_fields"]["default_tag"]
    end
  end
  require 'categories_controller'
  class ::CategoriesController
     before_action :convert_default_tag , only: [:create]
  end

أعتقد أنه من الممكن تعريف دالة default_tag داخل المتحكم نفسه، لكنني لم أستطع جعلها تعمل بهذه الطريقة. بما أن ApplicationController هو الذي يرث منه كل متحكم في Discourse، فإن الدالة يتم تحميلها عند بدء توسيع الفئة من ApplicationController، وهو ما يحقق المطلوب.

@merefield
هل من الممكن تعريف دالة تُسمى :before_action داخل المتحكم نفسه؟

يجب أن تضع ثلاثة علامات اقتباس قبل وبعد كتلة الكود.

```
 ضع الكود هنا
  ```

لا أستطيع الانتظار لتجربتها غدًا! شكرًا جزيلاً.

شكرًا لك. ظننت أن العلامة الأحادية (backtick) تكفي، لكنني علقت. لذا استخدمت وسوم HTML التقليدية

 لجعل الأمر يعمل.

نعم، أعتقد ذلك

هذا مساعد كبير. الآن لدي هذا:

  class ::CategoriesController
    before_action :default_tag_to_string, only: [:create, :update]

    def default_tag_to_string
      puts "CDT: #{params}"

      return unless :topic_default_tag_enabled
      #فقط تحقق مما إذا كان الحقل موجودًا لتجنب الوقوع في أخطاء
      request.params["custom_fields"]["default_tag"] = request.params["custom_fields"]["default_tag"].join('|')
      p request.params["custom_fields"]["default_tag"]
    end

  end

والآن يتم تحويل العلامات المحددة إلى سلسلة نصية قبل أن يحاول Rails تحديث السجل، ويعمل كما هو متوقع.

الآن المشكلة هي أنني بحاجة إلى معرفة مكان تحويل السلسلة النصية في موقع Rails إلى المصفوفة التي نحتاجها في جانب JavaScript/Ember. @j.jaffeux، لا أستطيع أن أتذكر (أو، الأرجح، لم أفهم) ما إذا كانت المشكلة التي كنت تحاول حلها هي إعادة كتابة هذه القيمة في جانب JavaScript إلى Rails (تم إصلاحها!) أم في جانب Rails إلى JavaScript (لا يزال الأمر محيرًا).

ما نجح معي هو أنني غيّرت :before_update إلى :before_commit في كودك عند تعيين الوسوم للموضوع.

ثانيًا، عند فتح صفحة تعديل الفئة، يتطلب حقل إعداد الوسوم الافتراضي مصفوفة في معامل الوسوم الخاص به لعرض الوسوم المحددة.