Ruby, Active Record и Sinatra

Я создал базовый веб-интерфейс API с помощью Sinatra и Active Record для поддержки фронтенда React. Здесь я расскажу о некоторых ключевых моментах, связанных с созданием серверной части этого приложения.

Отношения «один ко многим

Таблицы в этой базе данных имеют отношения «один ко многим». Я создал две таблицы, маршруты и спортсмены. Одна тропа «принадлежит» многим спортсменам. Ниже на диаграмме отношений сущностей показано, что внешний ключ trail_id в таблице athletes связан с id в trails.

Диаграмма отношений между сущностями:

Активная запись

Я наследую от Ruby gem Object Relational Mapper, Active Record, чтобы определить отношения между двумя классами, спортсменами и трейлами в файлах приложения/модели:

class Athlete < ActiveRecord::Base
    belongs_to :trail
end
Войти в полноэкранный режим Выход из полноэкранного режима
class Trail < ActiveRecord::Base
    has_many :athletes
end
Войти в полноэкранный режим Выйти из полноэкранного режима

Я использую команды Rake для создания файлов миграции:

Я определяю структуру таблиц базы данных в файлах db/migrate:

class CreateAthletes < ActiveRecord::Migration[6.1]
  def change
    create_table :athletes do |t|
      t.string :name
      t.string :time
      t.integer :trail_id
      t.boolean :unsupported
      t.timestamps
    end
  end
end
Войти в полноэкранный режим Выйти из полноэкранного режима

Важно помнить о необходимости следовать соглашениям Active Record об именовании, используя snake_case для имен файлов миграции и CamelCase для имен классов, а также сохраняя временную метку файлов миграции.

Также важно определить имена таблиц как множественное число, а имена классов — как единственное. При определении отношений таблиц следует использовать троп единственного числа belongs_to и множественного числа has_many при связывании таблиц.

Active Record ожидает эти соглашения об именовании, чтобы распознать ассоциации между данными; «конвенция над конфигурацией». Временные метки файла миграции позволяют Active Record управлять контролем версий/схемой.

В файле app/controllers/application_controller я наследую от Sinatra(Controller), чтобы фронтенд (View) мог подключаться к базе данных (Model).

Файл schema.rb показывает текущую версию базы данных. Номер версии соответствует временным меткам в файлах миграции — именно так Active Record поддерживает контроль версий.

ActiveRecord::Schema.define(version: 2022_07_20_184513) do

Я использую динамическую маршрутизацию для обработки действий CRUD. Например, со стороны клиента POST-запрос будет выглядеть следующим образом:

    const handleAddTrail = (newTrail) => {
      fetch("http://localhost:9292/trails", {
          method: 'POST',
          headers: { 
            "Content-Type": "application/json", 
          },
          body: JSON.stringify(newTrail),
        })
        .then(r => r.json())
        .then((newTrail) => handleAddTrailToTrails(newTrail))
  }
Войти в полноэкранный режим Выйти из полноэкранного режима

Со стороны сервера:

  post '/trails' do
    trail = Trail.create(
      name: params[:name],
      location: params[:location],
      distance: params[:distance],
      elevation_gain: params[:elevation_gain]
    )
    trail.to_json(include: :athletes)
  end
Войти в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше примере POST-запроса важно помнить об использовании include: для доступа к связанным данным между таблицами. В противном случае в данном примере возвращаемый объект newTrail не будет включать массив спортсменов [].

Общие мысли об Active Record и Sinatra

Изучение кода и создание базы данных с помощью этих инструментов не было слишком сложным процессом. Проблемы, на которых я зацикливался, были связаны с файловой структурой бэкенда и спецификой соглашений об именах.
Я также начал с большого количества кода в файле application_controller для обработки запросов, прежде чем понял, что связанные данные означают, что мне нужна только первоначальная выборка из таблицы trails, чтобы также получить все данные, которые мне нужны от спортсменов.

Оцените статью
devanswers.ru
Добавить комментарий