В этом руководстве, состоящем из нескольких частей, мы создадим приложение Ruby on Rails, которое реализует внешний вид и функции популярного гиганта социальных сетей Instagram. Мы будем использовать Rails 6, Webpacker 4, Turbolinks, Stimulus Js и Tailwindcss.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: хотя цель этого руководства - поделиться знаниями и показать, как реализовать определенные функции для обучения, из-за его длины и текстового формата оно не предназначено для начинающих разработчиков Rails и не является введением. в рельсы. Если вы все еще не знакомы со структурой приложения Rails, я рекомендую сначала начать с некоторых базовых руководств по Rails.
Я установил приложение Rails 6 (версия rc1) с Webpacker 4, Turbolinks и предстоящим выпуском 1.0 Tailwindcss. Если вы хотите продолжить, вы можете клонировать приложение из следующей ветки:
git clone -b tutorial-start [email protected]:rodloboz/railstagram.git
Чтобы запустить шаблон, на вашем компьютере должен быть установлен ruby 2.5.3
, а затем запускаться из терминала в папке клонированного проекта:
bundle install yarn install rails db:create db:migrate db:seed rails s
Цель состоит в том, чтобы больше сосредоточиться на способе реализации функций Rails (backend и frontend) и меньше на частях HTML и CSS, поэтому мы не будем слишком углубляться в эти темы. Таким образом, к указанной выше ветке уже применен некоторый стиль с Tailwindcss и Fontawesome, воссоздающий внешний вид Instagram.
Но прежде чем мы начнем, краткое введение в Tailwindcss:
В отличие от Bootstrap, Foundation, Bulma, Tailwindcss не является комплектом пользовательского интерфейса (нет темы или встроенных компонентов пользовательского интерфейса). Согласно документации:
Tailwind предоставляет легко компонуемые низкоуровневые служебные классы , которые упрощают создание сложных пользовательских интерфейсов , не заставляя любые два сайта выглядеть одинаково.
Он адаптивен и предоставляет инструменты для извлечения классов компонентов из повторяющихся служебных шаблонов, что упрощает создание собственных пользовательских компонентов пользовательского интерфейса:
// Using Tailwind's utility classes to // create variations of buttons .btn-blue { @apply bg-blue-500 text-white; } .btn-white { @apply text-blue-500 } .btn-white:focus { @apply text-blue-400 }
Tailwind написан на PostCSS и настроен на JavaScript. Поэтому я поместил компоненты в app / javascript / stylesheets для компиляции с помощью Webpack. Вы можете найти основной файл конфигурации Tailwind в app / javascript / stylesheets / config / tailwind.config.js
Модель пользователя
Мы используем Devise для регистрации и входа пользователей. Instagram требует, чтобы пользователи регистрировались со своим полным именем и именем пользователя в дополнение к обычным электронной почте и паролю, которые Devise уже включен по умолчанию.
Сгенерируем миграцию в терминале:
rails g migration AddAttributesToUsers full_name username:string:uniq about:text
Это генерирует следующую миграцию:
Instagram использует имя пользователя для создания URL-адресов профилей пользователей. Таким образом, имена пользователей должны быть уникальными, поэтому мы добавляем это ограничение в базу данных при миграции. Он также добавляет столбец about, который мы реализуем позже.
Не забудьте rails db:migrate
применить перенос.
Давайте также добавим проверку модели пользователя, которая отражает требование уникальности. Мы также хотим, чтобы имена пользователей состояли только из буквенно-цифровых символов, а не только из цифр. Для этого мы воспользуемся регулярным выражением. Проверка также должна быть нечувствительной к регистру.
validates :username,presence: true, format: { with: /\A(?=.*[a-z])[a-z\d]+\Z/i }, uniqueness: { case_sensitive: false }
Instagram не требует от пользователей подтверждения пароля и позволяет им входить в систему со своим адресом электронной почты или именем пользователя. Перейдите к просмотрам, созданным устройством, и удалите поле подтверждения пароля из registrations#new
и sessions#new
.
Нам нужно разрешить пользователям указывать дополнительные параметры в форме регистрации. Добавьте это в ApplicationController
.
Это позволяет добавлять дополнительные атрибуты к сильным параметрам Devise.
Нам нужно будет изменить нашу навигационную панель, чтобы отображать аватар пользователя и раскрывающийся список, чтобы вошедшие в систему пользователи могли выйти. Вы можете увидеть обновленный код здесь: https://github.com/rodloboz/railstagram/blob/master/app/views/shared/_navbar.html.erb
Примечание. Если вы следуете инструкциям, вам также необходимо добавить в файл конфигурации попутного ветра следующее:
// app/javascript/stylesheets/config/tailwind.config.js variants: { borderColors: ['responsive', 'hover', 'focus', 'group-hover'], visibility: ['responsive', 'group-hover'], }
И создайте раскрывающийся компонент CSS:
Мы также воспользуемся помощником просмотра, чтобы определить правильный URL аватара пользователя. Пока мы не реализуем загрузку изображений, есть только два варианта: мы проверяем, связан ли адрес электронной почты пользователя с учетной записью Gravatar. Если нет, мы отображаем изображение аватара пользователя по умолчанию:
Разрешение пользователям входить в систему с именем пользователя
По умолчанию Devise позволяет пользователям войти в систему и сбросить пароль, указав свой адрес электронной почты. Instagram позволяет пользователям указывать имя пользователя или адрес электронной почты. Для этого нам нужно переопределить настройки Devise по умолчанию.
Добавьте логин в качестве средства доступа к атрибуту в модель пользователя: attr_accessor :login
Измените config/initializers/devise.rb
, чтобы:
config.authentication_keys = [:login]
И переопределите find_for_database_authentication
метод Devise в модели пользователя:
Вы можете следовать этой вики, чтобы сделать то же самое для восстановления пароля: https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign_in-using -их-имя-пользователя или адрес электронной почты
На этом этапе вы должны протестировать свое приложение, чтобы убедиться, что оно работает, прежде чем двигаться дальше.
Рефакторинг модели User с учетом модели.
К настоящему времени ваша модель User начинает выглядеть толстой, с множеством методов разработки, а мы только начали. Давайте выделим весь этот код в модельную проблему. Создайте файл в app/models/concerns/authenticable.rb
и переместите весь этот код из модели в этот файл:
Затем все, что вам нужно сделать, это добавить include Authenticable
к модели User. Обязательно проверьте это снова.
Профиль пользователя
Instagram использует имена пользователей в корне своих URL-адресов для доступа к профилям пользователей. Для этого нам понадобится следующий маршрут:
resources :users, path: '/', param: :username, only: %i[show]
Это создает маршрут show в корне нашего приложения, который захватывает имя пользователя в параметрах и отправляет его в userscontroller # show. Затем нам нужно указать нашей модели пользователя, как сгенерировать параметры URL-адреса для себя:
# User def to_param username end
Здесь я добавил еще несколько классов, чтобы стилизовать интерфейс и придать ему ощущение Instagram. Помните, что мы используем Tailwindcss, поэтому все наши пользовательские компоненты создаются в app / javascript / stylesheets / components. Вы можете ознакомиться с полным кодом в репозитории Github, доступном в конце этого руководства.
Следующие пользователи
Наконец, мы собираемся добавить возможность подписаться на других пользователей. Это может быть достигнуто с помощью таблицы соединения, которая соединяет двух пользователей: подписчика, на который ссылается столбец follower_id
, и подписчика, или пользователя, за которым подписчик подписывается, на которого ссылается столбец following_id
. Сгенерируем модель:
rails g model Follow
Измените миграцию соответствующим образом:
И извлеките код в соответствующую проблему:
Обновите маршруты:
Мы будем пространство имен FollowsController для пользователей и использовать действие create (с именем follow_path), которое вызывает метод follow. мы реализовали выше в проблеме и действии уничтожить (названном unfollow_path), которое вызывает действие отменить подписку, реализованное в той же проблеме. Оба действия находятся в одной и той же конечной точке /:username/follow
, и мы используем HTTP-команды POST и DELETE, чтобы различать их. (более подробную статью о возможностях маршрутизации Rails вы можете прочитать здесь).
Во-первых, мы убеждаемся, что кнопка подписаться / отменить подписку в представлении работает правильно с помощью обычного HTML-запроса. Затем мы jaxify добавляем параметр remote: true
к этим ссылкам. Это отправляет запрос AJAX на бэкэнд вместо перезагрузки всей страницы, а затем мы обновляем кнопку и соответствующую ссылку с помощью javascript. Для этой цели я извлек код кнопки в часть представления: app/views/users/_follow_btn.html.erb
Счетчик кеширования
Мы хотим, чтобы на странице профиля отображалось количество подписчиков у пользователя и количество пользователей, на которых он подписан, как это делает Instagram. Мы могли бы использовать ActiveRecord для запроса базы данных и подсчета соответствующих записей Follow, но мы воспользуемся функцией Rails, которая называется кэширование счетчика.
Во-первых, нам нужно добавить два столбца в нашу модель User, которые будут отслеживать эти два счетчика при следующей миграции:
Затем мы добавляем параметр counter_cache в модель Follow. Это указывает Rails обновлять столбцы User с правильным счетчиком подписчиков и следующих каждый раз, когда создается или уничтожается запись Follow.
Затем обновите наше представление этими двумя новыми столбцами, а также отредактируйте create.js.erb
, чтобы представление обновлялось во время запросов AJAX:
Поскольку экземпляр @user
загружается до срабатывания counter_cache и до обновления столбцов счетчика каждый раз, когда пользователь подписывается на другого пользователя или отменяет его подписку, нам необходимо перезагрузить экземпляр в чтобы отображать правильное количество подписчиков и подписок. Мы делаем это, добавляя @user.reload
внутри блока в действиях create и destroy FollowsController.
Наконец, мы добавим Стимул, чтобы обеспечить множественное число в количестве подписчиков. Мы могли бы использовать метод Rails pluralize
, но Stimulus нам пригодится и позже.
Установите стимул в терминал:
bundle exec rails webpacker:install:stimulus
Стимул работает, добавляя в HTML-элементы представления атрибуты данных, которые ссылаются на контроллеры и цели и действия по событию. В нашем users#show
представлении мы добавляем контроллер к элементу заголовка: <headerclass="flex mb-16" data-controller="follow-button">
.
Затем нам нужно указать целевой элемент, в котором мы будем считывать фактическое количество подписчиков, и целевой элемент, в который мы вставим слово Follower в единственном или множественном числе. Это делается путем добавления атрибута data-target
к соответствующим элементам:
Затем мы настраиваем нашу кнопку отслеживания / отмены подписки для прослушивания события ajax:success
с атрибутом data-action
и обновляем сообщение / слово подписчика с помощью стимула:
А контроллер стимула выглядит так:
Это все для части 1 этого руководства. Мы продолжим наш клон Instagram в Части 2. Вы можете проверить полный код этой части здесь 👉 https://github.com/rodloboz/railstagram/tree/tutorial-part1
ПРИМЕЧАНИЕ. Большое спасибо Juliette Chevalier за предложения по улучшению этой статьи и за устранение опечаток и ошибок.