Теперь, когда я начал изучать Javascript, я, наконец, вижу общую картину. Возможность общаться с моей базой данных через Rails, меняя то, что я вижу в своем браузере, странно удовлетворяет, и я чувствую себя достаточно комфортно с Rails в режиме API, чтобы расшириться и попробовать что-то новое. С самого первого дня я использовал SQLite, но интересовался нереляционными базами данных (NoSQL). Об их отличиях я написал краткий блог, который вы можете прочитать здесь. После создания нескольких небольших приложений я решил попробовать перенести одно из них на MongoDB и посмотреть, насколько это будет сложно. Скажем так, ничего не зная о MongoDB, не было его преимуществ, поэтому я создал простое приложение с двумя моделями, книгами и обзорами.

Установка и запуск MongoDB

Первый шаг — установить MongoDB:

brew install mongodb

Запустить и завершить работу сервера mongo очень просто:

brew services start mongodb
brew services stop mongodb

Настройка Rails и MongoDB

Чтобы заставить работать Rails и MongoDB, необходимо сделать несколько вещей, поскольку MongoDB не является реляционной базой данных. Во-первых, при создании нового приложения rails вы должны добавить аргумент, чтобы Rails не использовал Active Record. В моем проекте я также должен был убедиться, что Rails находится в режиме API, и мне не нужен тестовый фреймворк:

rails new "Project" --api --skip-active-record --no-test-framework

Второе, что важно, это настроить гемфайл с Mongoid, который является официально поддерживаемым фреймворком для использования MongoDB в Ruby. Поскольку я использовал fetch API в Javascript, мне пришлось включить гем rack-cors. При использовании стоек-коров не забудьте раскомментировать или отредактировать нужный код в файле config/application.rb! Если вы забудете этот шаг, вы получите ошибки при попытке использовать выборку. Не волнуйтесь, вы можете исправить это позже и перезапустить сервер rails. Наконец, поскольку я также планировал заполнить свою базу данных, я включил faker gem для создания моих исходных данных:

Как только ваш gemfile будет готов к работе, запустите установку пакета, а затем сгенерируйте файл конфигурации Mongoid:

bundle install
rails g mongoid:config

Это создало файл mongoid.yml, которого было достаточно для этого проекта без необходимости его редактирования. В самой простой форме файл конфигурации задает для клиента по умолчанию значение «localhost:27017» и создает имя для базы данных, связанной с проектом. Однако мне по-прежнему приходилось использовать клиент Rails по умолчанию для запросов на выборку к моей базе данных.

Настройка API

Следующим шагом будет изготовление моделей. Я решил использовать генератор ресурсов:

rails g resource title author description genre isbn
rails g resource review content

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

Вот тут-то и начались сложности. Обычно я бы использовал Active Record, чтобы легко установить связь между книгами и обзорами. У книг много рецензий, а рецензия принадлежит книге. MongoDB не делает этого таким же образом, и, прочитав документацию Mongoid, я нашел два подхода для своих конкретных моделей.

Книга имеет_многоотзывов и обзор принадлежит_к книге. Это похоже на использование Active Record и создает внешний ключ в дочерней модели (belongs_to).

Книги embedded_many и рецензирование embedded_in книги. Это поместит отзыв в массив отзывов в книге и не создаст внешний ключ.

Я решил использовать более позднюю версию, так как она явно отличалась от Active Record, и я хотел попробовать что-то новое. Дополнительным преимуществом было то, что мне не нужно было беспокоиться о включении обзоров в объект книги при рендеринге моего JSON. Если бы я использовал Active Record, мне нужно было бы сделать следующее в моем books_controller:

def index()
    @books = Book.all
    render json: @books, include: [:reviews]
end

Мои модели выглядели так:

Заполнение базы данных

Наконец, когда мои модели были готовы, я заполнил базу данных. Обычно с Active Record я просто запускал что-то вроде:

new_book = Book.create(title: 'title', author: 'author')
new_review = Review.create(content: 'content', book: new_book)

Поскольку я использовал MongoDB, мне пришлось действовать немного по-другому. Сначала мне нужно было создать каталог 'db' и файл 'db/seeds.rb'. Я предполагаю, что это было результатом того, что Active Record не использовался, потому что Mongoid позволяет использовать 'rake db:seed'. Мне также нужно было создать обзор при создании книги:

Одна интересная вещь, которую я обнаружил после заполнения, заключалась в том, что если я вызываю Review.all.entries, я ничего не получаю в ответ. Обзор не содержит записей! Объекты Review располагались только в объектах Book. Как я уже сказал, я ничего не знал о MongoDB, но предполагал, что он создаст запись, которую я мог бы вызвать из класса Review, точно так же, как Active Record. Это могло быть что-то, что я сделал неправильно, или просто то, как все работает при использовании встраивания, но на самом деле это не имело значения. Меня заботило только то, что я мог получить доступ к обзорам через книги, которые действительно работали. Ниже приведен JSON из запроса на выборку для моего books_controller:

Результаты

Я успешно использовал Rails и MongoDB без особых проблем. У меня были небольшие проблемы с использованием метода PATCH с выборкой, когда я хотел добавить новый отзыв. По какой-то причине я продолжал получать ошибки, пока не переключил метод на PUT. Несмотря на небольшие проблемы, которые у меня были — например, мне потребовалось 30 минут, чтобы понять, что мне нужно ввести 'Book.all.entries' вместо 'Book.all' — я действительно понравилось использование MongoDB. С Rails он не кажется таким совершенным, как с Active Record, но этого и следовало ожидать, поскольку Rails был создан с учетом Active Record. В будущем мне бы очень хотелось узнать и сделать больше с MongoDB, например, добавить пользователя в свое приложение или использовать что-то другое, кроме Rails, в качестве серверной части. Если вы хотите посмотреть на код, который я использовал для этого проекта, его можно найти здесь.