Переопределение user_guardian.rb в плагине (форк не требуется!)

Привет, извините за вопрос новичка. Я читал документацию, но мне нужна небольшая помощь.

Я сделал форк Discourse и внес свои изменения, которые теперь хочу развернуть самостоятельно. Руководство по вкладу описывает, как внести изменения и отправить PR, но в данном случае я не хочу создавать PR. Мне просто нужно взять мои небольшие изменения и запустить установку Discourse на их основе. Я думал, что для этого достаточно изменить эту строку, указав на свой репозиторий:

Я сделал это и выполнил установку, но мои изменения не отображаются, значит, я что-то делаю не так. Есть какие-то идеи? Спасибо!

РЕДАКТИРОВАНИЕ:
Для прозрачности и на случай, если кто-то знает более простой способ, вот что я пытаюсь сделать: разрешить анонимным пользователям менять свои имена пользователей, когда они входят в анонимный режим. Это так же просто, как изменить false на true в этой строке:

Если есть лучший способ, я готов выслушать. Но мне нужно включить только это. Я хорошо разбираюсь в Python, Java и многих других бэкенд-технологиях, но не знаю Ruby/JavaScript/HTML и т.д.

РЕДАКТИРОВАНИЕ 2:
Согласно сообщению, которое я увидел в другом месте, я обновил app.yml следующим образом:

run:
- exec:
 cd: /var/www/discourse
 cmd:
    - sudo -u discourse git remote set-url origin https://github.com/my/forked/discourse.git
    - sudo -u discourse git fetch origin
    - sudo -u discourse git checkout origin/master

После пересборки приложения всё ещё ничего не работает. Приложение запускается нормально, но мои изменения, похоже, не применяются.

Неужели нельзя упаковать ваши изменения в плагин и использовать его вместо этого?

Все, кто это делал, очень об этом жалели. И здесь вы не сможете получить много помощи.

Что бы вы ни делали, делайте это в виде плагина.

Хорошо. Есть идеи, как это можно сделать через плагин?

Привет, @leighno5

Исходя из личного опыта, я считаю, что написание плагинов для Ruby для решения тех задач, которые вы пытаетесь решить в своём «форке», гораздо проще реализовать через плагин, когда мы достаточно хорошо понимаем Ruby и Rails, чтобы легко писать плагины для Discourse (или модифицировать любой класс Rails).

Если мы не понимаем Rails и Ruby достаточно хорошо, чтобы написать плагин для Discourse, то, по моему опыту, форкить Discourse и лезть в ядро — это «ошибочный путь».

Думаю, аналогия будет такой (извините за простую идею):

«Кто-то с трудом ходит, поэтому решает вместо этого бегать».

Позвольте объяснить, если вы не против:

Прежде чем я начал писать приложения на Rails (ничего общего с Discourse) и пробовал создавать плагины для Discourse, я немного терялся и даже, кажется, немного раздражался на Discourse. Это как когда вы в первый раз пытаетесь ударить по гольф-мячу: он не летит прямо, и требуется много усилий, чтобы попасть в середину фэйрвея. Форкить Discourse — это как доставать большой драйвер на тренировочном поле, прежде чем вы научитесь играть короткими клюшками и делать чип-шоты и путты!

Я взял паузу в работе с кодом Discourse (это было много месяцев назад) и какое-то время занимался созданием нескольких приложений на Rails с нуля. И только после этого у меня начала формироваться «интуитивная» уверенность в Rails. После этого, когда я решил модифицировать Discourse (сейчас я использую в продакшене 6 собственных плагинов, написанных для Discourse), всё стало интуитивно понятным, а плагины, изменяющие ядро Ruby, казались слишком простыми.

Ruby очень гибок. Мы можем переопределить любой класс, любой объект. Мы можем пересмотреть каждый аспект Ruby. С некоторым опытом начинаешь восклицать: «ВАУ, я и не знал, что Ruby настолько гибок (и мощен)», и начинаешь «становиться опасным», потому что с Ruby и Rails можно летать, как Супермен. В тот момент мы находимся лишь в начале своего пути в Ruby и Rails, а не в его конце!

С знаниями Ruby и Rails, которые я приобрёл в 2020 году, зная то, что знаю сейчас, я бы никогда не стал форкать Discourse и вносить изменения в ядро Ruby и Rails, как вы предлагаете, потому что плагины позволяют слишком легко переопределять и модифицировать классы Ruby, если мы понимаем основы классов Ruby и основы метапрограммирования.

Думаю, что я хочу сказать, и простите за прямоту, это следующее: если кто-то считает, что ему нужно лезть в ядро Discourse, чтобы внести какие-то незначительные изменения в Ruby, значит, он недостаточно хорошо понимает Ruby и Rails. Потому что если бы он понимал, то не лез бы в ядро, а просто написал бы быстрый плагин для переопределения классов и с удовольствием занимался бы monkey-patching.

С другой стороны, если бы я хотел сделать что-то безумное и страдать, например, заменить EmberJS в Discourse на React и Ant Design, то форк был бы единственным выходом! Однако, на мой взгляд, «Discourse» определяется не «JavaScript-библиотеками». Discourse определяется навыками команды разработки ядра (людьми), их вниманием к деталям, качеством обслуживания клиентов, командным подходом к разработке открытого кода, их конвейером функций SPA и всем их тяжёлым трудом! Было бы немного безумием (на мой взгляд) выбросить весь этот интеллектуальный потенциал только потому, что нам может больше нравиться Ant Design (с React) или VueJS вместо Ember.

Это же справедливо ещё в большей степени, если мы просто собираемся понемногу менять ядро Discourse! Было бы немного «сумасшедшим» форкнуть его ради этого, выбросив «людей», которые и есть «настоящий» Discourse (а не код).

Я говорю это только исходя из своего личного пути в 2020 году, когда я изучал Ruby и Rails. Сейчас основы становятся лёгкими, и я «становлюсь опасным», ха-ха. Я могу «потыкаться с помощью monkey patching во что угодно», что не всегда хорошо; и именно для этого существуют плагины Discourse.

Держите ядро твёрдым как скала и наслаждайтесь «потыкиванием» в Discourse с помощью плагинов.

Надеюсь, это поможет.

Кстати, пока я писал этот ответ, вы написали:

Это, пожалуй, подтверждает мою точку зрения, не так ли?

Написание «плагина» в Discourse — это написание «кода на Ruby» (на одном уровне), а для других это уходит гораздо глубже (в EmberJS).

Прежде чем вы начнёте писать плагины для Discourse, мой дружеский совет, который, возможно, покажется вам не имеющим ценности, — сначала разработайте несколько приложений на Ruby on Rails. Изучите Ruby и Rails, хотя бы основы, и после этого вы сами ответите на свой вопрос выше.

Сегодня утром я три часа провёл в телефонной конференции с клиентом, обсуждая приложение на Rails, валидации, модели и т. д., а затем, взяв перерыв после реализации некоторых пунктов из обсуждения, я прочитал ваш пост.

Самый короткий путь к написанию плагинов для Discourse, на мой взгляд, — сначала изучить Rails.

Надеюсь, это поможет!

Хорошая отправная точка:

Нет, вы абсолютно правы. У меня вообще нет опыта работы с Ruby, так что обиды точно нет!

Я читал руководство по плагинам и проходил его пару раз, но, к сожалению, моё незнание Ruby продолжает вызывать раздражение, и я совершенно не представляю, как написать плагин, который переопределил бы этот небольшой фрагмент кода в файле user-guardian, чтобы разрешить анонимным пользователям менять свои имена. :confused:

Привет, @leighno5!

Да, я понимаю.

Эти темы с инструкциями «КАК СДЕЛАТЬ» были написаны очень талантливыми разработчиками, имеющими более десяти лет опыта программирования на Rails и Ruby (возможно, даже больше). На самом деле, некоторые из них входят в число лучших разработчиков Ruby и JS в мире.

Я на 100% уверен, что все они изучили Rails и Ruby задолго до того, как написали свой первый плагин для Discourse.

На самом деле, научиться Rails не так уж и сложно; но вам действительно нужно пройти «практический ритуал» создания нескольких приложений на Rails с нуля. Не просто следовать за видеоуроком на YouTube (что, конечно, хорошо), а создать работающее приложение, где вам придётся самостоятельно настраивать базу данных, генерировать свои модели, создавать свои контроллеры, писать валидации моделей, инициализаторы, модули помощников, выполнять миграции (изменения) БД, работать с встроенным Ruby и многое другое.

Это на самом деле очень увлекательно и является «кратчайшим путём» к тому, чтобы почувствовать себя комфортно при написании плагинов (что касается части Rails, я лично не очень глубоко погружался в Ember, но очень люблю сторону Rails)!

Также вам обязательно нужно освоить консоль Rails! Консоль Rails — это действительно весело, и я использую её каждый день с удовольствием!

Сегодня мой любимый клиент и я работали через AnyDesk, и он спросил: «Можно ли сделать новое представление для инвентаря?». Он хотел посмотреть, как я это сделаю. После того как всё заработало, в конце звонка он сказал: «Ты сделал в Rails за 30 минут то, что несколько десятилетий назад заняло бы многие недели!». Поистине впечатляюще, @leighno5. Дерзай!!

После того как вы освоите Rails, вы скажете: «ВАУ», что написание плагинов для Discourse довольно простое, по крайней мере, в части Rails и Ruby!!

Надеюсь, это поможет.

Посмотрите на существующий код #plugin. Их сейчас очень много, так что примеров в избытке. Не пропускайте изучение предыдущих наработок, чтобы использовать их в своей работе.

Похоже, вам нужно просто переопределить один метод, что делается путём его переопределения в файле plugin.rb (хотя, по мнению многих, лучшая практика — выносить каждый метод в отдельный файл модуля, но для одного метода это излишне).

На свой страх и риск, продолжая демонстрировать свою неосведомлённость и пользуясь вашей уже проявленной ко мне добротой, не могли бы вы немного подробнее раскрыть эту тему? Или, если вам известен другой пример, где кто-то переопределял модуль, я был бы признателен за ссылку на него. Я совершенно не против фразы «читай мануал» (RTFM), но мне крайне frustrating отсутствие понимания того, как работает Discourse, несмотря на все время, которое я потратил на изучение различных руководств и документации. Да, я понимаю, что такие базовые вопросы могут создать впечатление, будто я мало старался, но обещаю, что это не так!

Вот пример, где мы определили метод в PostGuardian:

Вы можете сделать что-то подобное для UserGuardian, используя существующее имя метода, которое должно переопределить исходный.

Простое решение (чтобы заставить это работать, хотя и не самым надежным способом):

Просто скопируйте код оригинального метода и внесите свои изменения. Недостаток: если Discourse изменит код, ваш плагин может нарушить работу экземпляра.

Продвинутое решение (более надежный вариант):

За дополнительные баллы вы можете попробовать использовать super, чтобы наследовать оригинальный метод, но это не гарантированно сработает по причинам, которые я не буду здесь подробно разбирать. Тем не менее, это лучшая практика, так как обновления этого метода в Discourse будут всегда учитываться без необходимости править ваш плагин.

Discourse — это платформа. На её изучение требуется время. Просто двигайтесь шаг за шагом.

Это именно то, чего я опасался. Описан ли продвинутый метод, упомянутый в вашем следующем абзаце, в руководстве? Есть ли хороший, простой пример его использования в существующем плагине, который можно было бы использовать (скопировать) при создании нового плагина?

Пока не стоит беспокоиться о продвинутом методе. Просто добейтесь, чтобы всё работало. Вы можете изучить Ruby on Rails в целом в других онлайн-руководствах. Это немного выходит за рамки темы Discourse и данного форума. Просто имейте это в виду.

Отлично, спасибо! Допустим, я напишу небольшой плагин. Если я всё правильно понял, мне следует проверять исходный код ядра при каждом обновлении и переписывать плагин, если соответствующий код ядра изменился. Всё верно? Спасибо.

Верно. Просто проверяйте это время от времени, особенно если начнутся сбои. Код Guardian немного критичнее, так как он отвечает за авторизацию на сайте кодирования, поэтому следите за ним внимательно.

Другое решение — добавить тест-кейсы (также известные как спецификации) и настроить автоматизированную задачу для их запуска… но это уже более сложный путь!

Еще одно дополнительное задание — настроить travis-ci.org для запуска тестов вашего плагина, чтобы вы получали уведомление, если что-то сломается.

Очевидно, это задача, к которой нельзя относиться легкомысленно. Я хотел бы изменить модальные окна входа и создания новой учётной записи, а также убрать изображение Twitter. Возможно, последнее было бы более подходящим первым проектом. Спасибо.

Если кто-то наткнётся на это и так же, как я, был в замешательстве, я привожу ниже свой код, который у меня заработал как задумано. Я не изменял никаких файлов. Я просто создал новый файл plugin.rb и поместил в него следующее:

# about: Позволяет пользователям в режиме анонимности менять свои имена
# version: 0.1


require_dependency 'guardian'
require_dependency 'guardian/user_guardian'

class ::Guardian
end

module ::UserGuardian
  def can_edit_username?(user)
    return false if SiteSetting.sso_overrides_username?
    return true if is_staff?
    return false if SiteSetting.username_change_period <= 0
    return true if is_anonymous?
    is_me?(user) && ((user.post_count + user.topic_count) == 0 || user.created_at > SiteSetting.username_change_period.days.ago)
  end


  def can_edit_name?(user)
    return false unless SiteSetting.enable_names?
    return false if SiteSetting.sso_overrides_name?
    return true if is_staff?
    return true if is_anonymous?
    can_edit?(user)
  end
end

Это переопределяет класс user_guardian.rb в ядре Discourse, позволяя пользователям менять имя пользователя и имя своих анонимных учётных записей.

Если вы сравните то, что у меня здесь, с тем, что находится в user_guardian.rb в ядре Discourse, вы увидите, что есть множество других вещей, с которыми мне не нужно было ничего делать, поэтому я оставил их без изменений. Всё, что мне потребовалось, — это отредактировать два метода can_edit_username и can_edit_name, изменив некоторые возвращаемые значения с false на true, и я смог решить свою задачу.

Конечно, можно было бы внести улучшения, и, вероятно, существуют лучшие практики, которые я смог почерпнуть, прочитав связанные сообщения здесь и в других местах, но если вы, как и я, только начинаете знакомство с Ruby и просто хотите внести очень простые изменения в ядро, то это рабочий минималистичный пример того, что нужно сделать.

Огромное спасибо всем участникам этой ветки за ваше терпение, поддержку и помощь! В особенности @merefield, который ранее уже помогал мне в другом сообщении.

LOL

Вы далеко ушли от первоначальной идеи форкнуть весь Discourse и отказаться от основной ветки ради таких простых задач.

Отличная работа :slight_smile:

Вы прошли весь путь по ссылке Install Discourse on Ubuntu or Debian for Development или просто работали над своим продакшн-сайтом и надеялись на лучшее?