47 Постов

В этом посте мы рассмотрим Bundler и управление gem’ами внутри вашего Rails-приложения.

Если вы зайдете на bundler.io, вы увидите, что «Bundler обеспечивает согласованную среду для проектов Ruby, отслеживая и устанавливая точные gem’ы и версии, которые необходимы».

Bundler

Bundler позволяет вам указывать gem’ы (и связанные с ними зависимости) для Rails-приложения внутри файла Gemfile (в его корневой директории).

Это наиболее предпочтительный способ управления зависимостями gem’ов в Rails.

Чтобы использовать его, выполните bundle install или просто bundle после указания нового gem’а в Gemfile.

Если вы изменяете версию gem’а, выполните bundle update.

Кроме того, вы можете сказать Rails (опять же, через Gemfile) загружать определенные gem’ы только в определенных окружениях.

К примеру, некоторые gem’ы можно указать только для среды разработки или тестирования.

Какая версия устанавливается

Если вы не указываете ничего, вы получаете последнюю версию.

Вы также можете указать точную или примерную версию.


gem 'rails', '4.2.6' # точная версия
gem 'sqlite3' # последняя версия
gem 'uglifier', '>= 1.3.0' # версия старше (или равная) 1.3.0

Другой пример:


gem 'thin', ">= 1.1", "< 2.0" # не менее 1.1, но менее 2.0
gem 'thin', "~>= 1.1" # то же, что и в примере выше

Подобное значение может указываться, потому что часто при переходе на новую версию gem’ы (и программное обеспечение вообще) могут менять или удалять определенные API.

Во втором варианте этого примера, bundler отбрасывает последнее число и увеличивает первое, чтобы получить верхний лимит номера версии.

Пример Gemfile

Приложение может даже использовать другую версию Rails, если вы меняете версию в Gemfile и выполняете bundle update.


source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.6'

Кроме того, Bundler создает файл Gemfile.lock, который содержит фактические версии gem’ов с их зависимостями, которые использует ваше приложение.

bundle exec

Скриншот документации:

Допустим, у вас есть три или четыре разные версии, скажем, rake. Может быть не так очевидно, какую из них использовать.

При выполнении bundle exec rake вы будете точно знать, что выполняется версия из Gemfile.

В итоге

Bundler управляет зависимостями gem’ов.

Он загружает gem’ы при запуске приложения.

В этом посте мы рассмотрим gem’ы в Ruby в общем, а также конкретный gem под названием HTTParty.

Итак, RubyGems — это, в целом, менеджер пакетов. Вы можете посмотреть информацию о нём на сайте rubygems.org. Там действительно можно найти сотни и тысячи сторонних gem’ов.

Также, Gem — это менеджер пакетов, который устанавливается вместе с установкой Ruby. Вы можете выполнять такие команды как gem install name.

Если вы хотите узнать, установлен ли gem, вы можете сделать gem list, в этом случае httparty.

Если он не установлен, выполните команду gem install httparty.

Вы также можете увидеть больше деталей о gem’е с помощью команды gem list httparty -d.

Что такое Restful веб-сервисы

Restful веб-сервисы это простые веб-сервисы реализованные с помощью HTTP (и принципов REST), которые:

  • Имеют базовый URI
  • Поддерживают форматы обмена данными такие как JSON и XML (и, возможно, другие)
  • Поддерживают набор HTTP-операций (GET, POST и т.д.)

Вместо того, чтобы думать о вебе в целом как о куче HTML-страниц, подумайте о нём как о том, что больше соответствует MVC-шаблону, который мы обсуждали.

Веб-сайт это что-то, что просто хранит какие-то ресурсы. Когда вы переходите на сайт, вы можете получить эти ресурсы в любом из форматов. Возможно, вы получите их в качестве HTML, возможно в качестве JSON или XML, которые могут быть разными форматами для представления одного и того же.

Некоторые форматы легче парсить, чем другие. К примеру, HTML не очень подходит для парсинга, но XML и JSON подходят хорошо.

Означает ли это, что вы должны изучить полностью новый формат и писать парсер для него в Ruby?

Нет, потому что это как раз то где на помощь приходит HTTParty.

Gem HTTParty

HTTParty это клиент для Restful веб-сервисов.

Представьте браузер. Ваш браузер является клиентом веб-сайта, и чаще всего вы видите HTML-страницы в нём.

Ваш браузер запрашивает что-то с сервера, сервер возвращает это, и браузер это отображает.

Но, опять же, эти данные трудно парсить. Поэтому, если вы хотите использовать их, к примеру, для коммуникации между двумя сайтами и запрашиваете информацию с другого Rails-приложения, вам больше подойдет формат который легко парсить, а не только легко отображать.

HTTParty обеспечивает автоматический парсинг JSON и XML в ваши хэши (или массивы) Ruby.

Пока формат является валидным JSON или XML, HTTParty легко парсит данные в структуры Ruby, и затем вы можете просто использовать их.

Использование HTTParty

Это, на самом деле, довольно просто. Включаете модуль HTTParty в код и вы готовы!

Вы также можете указать:

  • base_uri для ваших запросов
  • default_params (к примеру, ключ API)
  • format, чтобы указать в каком формате данные

Плагин JSONView

Для браузеров (Chrome, Firefox и возможно других) есть плагин JSONView, который позволяет удобно просматривать файлы JSON.

С этим плагином JSON API будет выглядеть примерно так:

В общем, рекомендую установить.

Пример URL в API

Пример URL в API:

Через ? указываются параметры, второй параметр (как и следующие) указывается через &.

В данном примере мы запрашиваем контент определенного изображения с параметрами высоты и ширины не ниже заданных размеров.

В итоге

HTTParty позволяет чрезвычайно просто интегрировать Restful-сервисы, конвертируя их в хэши Ruby.

Поддерживаются форматы JSON и XML.

В этом посте мы рассмотрим:

  • Что такое хелперы и чем они полезны
  • Зачем использовать Rails-хелпер link_to

Хелперы

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

Что если мы хотим форматировать то, как выглядит это время?

Должен ли этот код быть во View? Вряд ли, в этом случае он не будет многоразовым, то есть его придется определять каждый раз.

Должен ли он быть в контроллере? Вряд ли, потому что контроллер должен быть независим от формата представления.

Так что, здесь приходят на помощь хелперы.

Каждый раз, когда вы генерируете контроллер, также генерируется (пустой) хелпер.

Давайте добавим в него метод.

Интересно то, что метод внутри хелпера будет доступен для всех view в вашем приложении.

Не забываем указать formatted_time(@time) во view.

И это работает, на странице показывается отформатированное время.

Встроенные в Rails хелперы: link_to

Rails предоставляет много встроенных хелперов.

Один из них, это хелпер link_to.

link_to name, path генерирует гиперссылку, которая отображает имя (name) и ссылается на путь (path).

В вашем HTML вы будете иметь тег <a>.

Путь может быть обычной строкой или маршрутом указанным в файле routes.rb, и оканчиваться на _url (полный путь) или _path (относительный путь).

Это полезно потому, что вы можете указать переменную, и ваша страница изменится автоматически, если изменится эта переменная.

link_to в действии

Добавим пару ссылок в наш view.

Первый параметр это имя.

В первом примере мы ссылаемся на Google и определяем полный URL, во втором — используем внутренний путь, определенный в routes.rb.

Конечно, это будет работать без проблем.

В итоге

Хелперы являются «макросами» для вашего Представления.

При использовании link_to, нет необходимости что-то менять, когда меняется путь.
Поэтому он может быть удобнее простого HTML-тега.

В этом посте мы рассмотрим то, как перенести бизнес-логику из Представления в Контроллер в соответствии с MVC-паттерном.

Также мы поговорим о том, как долго переменные экземпляров контроллера остаются на месте.

Действия (методы) внутри контроллера

Если действие (метод) ничего не делает, мы можем просто убрать его.

Пока определен правильный маршрут и есть правильно названный файл/шаблон представления, действие не обязано присутствовать, и Rails найдет правильный шаблон при помощи конвенции.

Контроллер: новый вид

Так что, мы можем закомментировать (или просто удалить) действия в нашем контроллере, и он всё еще будет работать.

Но, конечно же, есть причина иметь действия внутри контроллера, они не просто для декорации.

Переносим бизнес-логику

Наше приложение работает, но бизнес-логика не должна находиться во View. Представление должно иметь настолько мало Ruby-кода, насколько это возможно.

Давайте перенесем эту бизнес-логику из Представления в Контроллер.

Переменные экземпляров из контроллера доступны внутри view.

Попробуем также добавить счетчик просмотров. Изначально, @times_displayed будет равняться 0, и с каждым просмотром страницы это число должно увеличиваться на 1.

Здесь мы просто используем переменные из контроллера.

Посмотрим что получилось.

В обоих случаях просмотрено 1 раз? Интересно.

Переменные экземпляров в Rails

Дело в том, что, в отличие от других веб-фреймворков (к примеру, Servlets), вы не можете хранить значения в переменных контроллера между запросами.

Таким образом, каждый новый запрос создает новую переменную экземпляра.

Какие альтернативы? Можно хранить их в HTTP-сессии, либо в базе данных.

В итоге

Старайтесь держать бизнес-логику вне View.

Переменные экземпляров в контроллере доступны для View.

Переменные экземпляров не задерживаются между запросами.

В этом посте мы рассмотрим как работает маршрутизация, что такое Rake и как анализировать ваши маршруты.

Маршруты

В предыдущем посте мы пытались добавить действие «goodbay» в наш контроллер, но это не сработало, потому что не хватало еще одной важной части. Этой частью является маршрутизация.

Перед тем как контроллер может скоординировать куда идет веб-запрос, этот запрос должен быть направлен к контроллеру.

Так как работало действие «hello»?

Маршрут к нему был автоматически сгенерирован, когда мы выполняли rails g controller.

Давайте дополним цикл MVC из одного из прошлых постов.

  1. Отправлен запрос
  2. Маршрутизатор направляет запрос к контроллеру
  3. Контроллер ← → Модель
  4. Контроллер запускает Представление
  5. Представление отображает данные

routes.rb

Все маршруты должны быть указаны (вручную или с помощью генератора) в файле config/routes.rb.

Как этой файл выглядит?

Изначально в нём много комментариев.

Запись get 'greeter/hello' означает, что когда вы отправляете get-запрос, к примеру в браузере, он должен быть интерпретирован как «контроллер greeter, действие hello».

Давайте добавим маршрут для действия goodbay.

Мы можем указать просто get 'greeter/hello' (или 'greeter/goodbay'), или мы можем указать это в стиле get 'greeter/hello' => "greeter#hello", что означает, что этот запрос направляется к «контроллер greeter, действие hello».

В данном примере они не имеют разницы, но если бы вы хотели указать другой адрес слева, вы бы использовали именно второй способ.

Итак, наш маршрут для goodbay работает.

Rake

Rake это язык сборки Ruby. Его имя происходит от «Ruby’s make».

В отличие, к примеру, от Ant в Java, он не написан на XML, он написан только на Ruby.

Rails использует Rake для автоматизации связанных с приложением заданий, к примеру операций с базой данных, тестами и т.д.

Чтобы увидеть список всех rake-заданий для вашего приложения, можно выполнить rake --tasks.

Также можно запросить описание индивидуального задания с помощью rake --describe.

rake routes показывает все ваши указанные маршруты.

В итоге

Маршрут направляет запрос к правильному контроллеру.

rake routes позволяет увидеть какие маршруты на данный момент определены в вашем приложении.

В этом посте мы затронем создание динамичного контента. Конкретно мы рассмотрим:

  • Как создать контроллер
  • Действия
  • Встроенный Ruby (ERB)

Создание контроллера

Контроллер содержит действия (методы Ruby) и координирует веб-запросы.

Rails может быстро сгенерировать контроллер с 0 или более действий с их ассоциированными представлениями.

Генерация происходит следующим образом:

rails generate controller controller_name [action1 action2]

Команда generate может быть сокращена до g.

Попробуем сгенерировать контроллер greeater, «hello» будет именем действия и именем представления.

Таким образом, мы получаем контроллер greeter.rb в папке app/controllers. Также получаем файл app/views/greeter/hello.html.erb.

Если вы заглянете в этот файл представления, вы увидите, что там нет типичных для HTML элементов Doctype, head или body. Мы увидим немного позже, почему.

Как это выглядит?

Встроенный Ruby (ERB)

Сгенерированный файл представления выглядит как типичный HTML-файл, но он также имеет расширение .erb.

ERB это библиотека шаблонизации (похожая на JSP, к примеру), которая позволяет вам встраивать Ruby в ваш HTML.

Стоит выучить два паттерна:

  • <% ...код ruby... %> — рассчитывает код
  • <%= ...код ruby... %> — возвращает рассчитанный код

И еще раз, идея ERB в том, чтобы иметь возможность включать динамичный контент в статичный HTML-контент, чтобы смешивать их вместе.

Так что, к примеру, мы можем переписать нашу приветственную страницу.

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

Теперь при обновлении страницы, она показывает случайное имя из списка.

Как выглядит контроллер

Итак, это была часть про представление. Как же выглядит сам контроллер?

hello это просто действие. Это обычный метод Ruby, в данном случае пустой.

И это работает.

А что если мы хотим добавить действие «goodbay» в этот контроллер, и также goodbay.html.erb в папку app/views/greeter?

Давайте попробуем.

Создаем файл для view в соответствующей папке, затем редактируем контроллер.

Заходим на страницу /greeter/goodbay:

Не сработало. Так как в этом случае не хватает компонента, который мы собираемся рассмотреть в следующем посте.

В итоге

Контроллеры содержат действия (методы).

ERB позволяет рассчитывать выражения с помощью паттерна <% expression %> или выводить их с помощью <%= expression %>.

В этом посте я расскажу о том как создать и запустить ваше первое приложение, о структуре каталогов и о добавлении статических страниц.

Чтобы создать свое первое приложение, перейдите в каталог, в котором хотите его создать. Введите rails new my_first_app, где «my_first_app» — имя приложения.

Это создаст определенную структуру, о которой я расскажу немного ниже.

Вы также можете выполнить rails new -h, в этом случае вы увидите какие параметры вы могли бы указать при создании нового Rails-приложения.

Bundler (менеджер gem’ов)

Ближе к концу создания приложения вы увидите «bundle install». Его идея заключается в том, что в приложении у вас имеется множество разных компонентов, которые объединяются вместе и имеют разные версии, и, очевидно, они должны взаимодействовать.

Один компонент может зависеть от одной версии, другой компонент от другой. И вам нужно разрешить эти зависимости, — это то что делает Bundler.

Контроль версий вашего приложения

Итак, сейчас ваше приложение создано. Rails сгенерировал изначальный скелет и даже немного кода.

Также интересно, что Rails автоматически создает файл .gitignore, что показывает, что он подталкивает вас к использованию Git.

Создаем репозиторий и делаем наш первый коммит:

cd my_first_app
git init
git add .
git commit -m "Initial commit"

Запускаем приложение

Кроме создания скелета приложения, Rails также имеет встроенный веб-сервер.

Так что, чтобы запустить приложение, вам не нужно ничего скачивать или ставить костыли.

Опционально открываем новое окно терминала, переходим в нужную директорию (cd my_first_app) и выполняем:

rails server

Либо rails s, что является той же командой в сокращенном виде.

Здесь говорится о версии Rails, о режиме в котором вы находитесь (development, т.е. разработки) и адресе по которому запущено приложение (http://localhost:3000).

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

Когда вы развернете ваше приложение, к примеру на Heroku, оно будет работать в режиме production.

Открываем в браузере localhost:3000, и Rails уже приветствует нас.

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

Конвенция структуры директорий

Итак, приложение будет иметь директорию app, на которую вы будете тратить большую часть времени. Она включает модели, контроллеры и представления (папки controllers, models и views), а также хелперы и прочее.

Следующая интересная директория это config, она включает различные конфигурации, к примеру какую БД вы собираетесь использовать и пароль от нее.

Папка db будет иметь скрипты миграций вашей базы данных, а также сам файл БД если вы используете SQLite (которая используется по умолчанию).

Папка public содержит статичные файлы. К примеру, HTML-файлы, которые вы редко будете изменять, пойдут в эту папку.

Gemfile и Gemfile.lock используются Bundler’ом для разрешения зависимостей. Здесь вы указываете нужные gem’ы.

public / hello_static.html

Мы упоминали, что статичные файлы идут в папку public.

Сервер проверяет папку public перед тем как проверить всё остальное. Если файл найден в этой директории, он просто отображается по ссылке.

Так что, если вы хотите добавить полностью статичную страницу, вы добавляете её в эту папку.

Попробуем добавить такой файл.

Переходим на localhost:3000/hello_static.html. Если ваш сервер уже запущен, нет нужды перезапускать его.

В большинстве случаев, конечно, вы захотите создавать динамические страницы, которые, к примеру, будут использовать данные из базы данных или из других мест.

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

В итоге

rails new создает новое приложение.

rails server / rails s запускает его (нужно выполнять в папке с самим приложением).

Статичные страницы находятся в папке public.

Мы рассмотрели Ruby, теперь можно переходить к Ruby on Rails. В этом и следующих постах мы будем обсуждать основные принципы, конвенции и MVC-структуру.

Итак, в этом посте я расскажу о следующих вещах:

  • Краткая история Rails
  • Польза от использования Rails
  • Model View Controller

История Ruby on Rails

Rails (RoR) — это фреймворк для разработки динамичных веб-приложений.

Он был создан в 2004-2005 годах Давидом Ханссоном (который, кроме того, является автогонщиком).

Кто использует Rails?

Так кто использует Rails? Много больших, а также средних сайтов, таких как Hulu, Groupon, LivingSocial, Twitter и Github.

Стартапы в целом любят Rails из-за его возможности быстро прототипировать и быстро разрабатывать приложения.

Почему Rails?

Один из принципов использования Rails называется Convention Over Configuration.

Вы бы могли подойти к разработке приложений по одному из двух путей. В одном из них вы настраиваете всё что вы делаете с чистого листа.

Или вы можете положиться на конвенции, которые уже были установлены. Многие лучшие практики уже существуют в конвенциях.

И если вы следуете определенным конвенциям, вам нужно писать меньше кода — иногда фреймворк генерирует его за вас.

Другим преимуществом этого паттерна является то, что вы изучаете разработку проекта один раз, и вы можете применить те же самые концепты в следующем Rails-проекте.

Так что, вы будете знать чего ожидать в следующий раз.

Следующее преимущество Rails — это то что у вас есть уровень абстракции базы данных. Ruby on Rails позволяет вам взаимодействовать с базой данных не путем написания SQL-запросов, вы можете взаимодействовать с базой данных путем написания Ruby-кода.

Это иногда называется ORM, то есть объектно-реляционное сопоставление.

Вы сопоставляете свою базу данных с вашими классами Ruby.

Кроме того, Rails:

  • Благоприятен для гибкой разработки
  • Следует принципу «не повторяйся» (Don’t repeat yourself)
  • Кроссплатформенный
  • С открытым исходным кодом
  • Модульный

SQLite

Другой интересной особенностью Rails является то, что он использует SQLite как базу данных по умолчанию.

SQLite — это автономная, безсерверная, транзакционная база данных SQL нулевой конфигурации.

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

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

Когда вы создаете Rails-приложение, возможность взаимодействия с базой данных находится прямо «в коробке».

Поскольку база данных здесь абстрактна, вы можете переключиться на другую СУБД позже, если захотите. Но в самом начале вам не нужно проходить эти детали настройки.

Кроме того, SQLite является наиболее широко распространенной SQL-базой в мире. Ее используют браузеры, iPhone, Android и многие большие приложения. Потому что, опять же, она ведет себя как реляционная база данных, но в реальности это всего лишь файл.

MVC: Module, View, Controller

Еще одна концепция, которую использует Rails, — это идея Model View Controller. На русский это переводится как «Модель-Вид-Контроллер» или «Модель-Представление-Контроллер».

MVC изобрел норвержский профессор Трюгве Реенскауг в 1979 году.

Это хорошо зарекомендовавший себя программный паттерн, используемый многими веб-фреймворками и десктопными фреймворками.

Model — представляет собой данные, с которыми работает приложение (и, возможно, бизнес-логику).

View — визуальное представление этих данных.

Controller — координирует взаимодействие между моделью и представлением.

Цикл MVC

  1. Отправлен запрос
  2. Контроллер ← → Модель
  3. Контроллер запускает Представление
  4. Представление отображает данные

MVC в Rails

В итоге

В итоге, Rails очень хорошо подходит для быстрого прототипирования.

Использование паттернов и конвенций позволяет меньше думать и больше делать, таким образом увеличивая продуктивность разработчика.

В этом посте мы продолжим разбирать RSpec и поговорим о matchers.

«Matchers» не переводится с английского, но слово match в этом контексте означает «совпадать, равняться».

Итак.

RSpec «вешает» методы to и not_to на все результаты ожиданий.

Эти два метода принимают один параметр — matcher.

Примеры matcher’ов:

  • be_true / be_false
  • eq 3
  • raise_error(SomeError)

Be_predicate — логическое значение

Если объект, на котором проводится тест, имеет утвердительный (логический) метод, вы автоматически получите матчер be_predicate.

Так что, к примеру, be_nil является валидным матчером, так как каждый объект в Ruby имеет метод :nil?.

В нашем примере с калькулятором мы можем иметь такой тест:


it "should sum two odd numbers and become even" do
 expect(@calculator.add(3, 3)).to be_even
 expect(@calculator.add(3, 3)).not_to be_odd
end

Это полностью валидно и выглядит почти как естественный английский.

Так как мы исправили ошибки в калькуляторе, все тесты работают.

Но если вы хотите узнать подробнее, что работает, а что нет, введите rspec --format documentation или rspec -f d:

Больше матчеров

Полный список матчеров можно найти в документации RSpec.

https://relishapp.com/rspec/rspec-expectations/v/3-6/docs/built-in-matchers

В итоге

RSpec имеет множество встроенных матчеров, которые доступны для упрощения написания тестов, я думаю это отличный фреймворк для тестирования приложений.

Хотя если вы предпочитаете MiniTest, используйте его.

В этом посте мы продолжим говорить о юнит-тестировании в Ruby и рассмотрим RSpec.

Тестирование с помощью RSpec

Test::Unit делает свою работу, но было бы неплохо, если бы тесты были более описательными, более похожими на естественный английский.

RSpec позволяет это.

Так что, здесь написание тестов более интуитивно, как и вывод после выполнения тестов.

Установка RSpec

Устанавливаем RSpec командой gem install rspec.

describe()

Метод describe() это набор связанных тестов.

Он принимает строку либо класс в качестве аргумента.

Все тесты должны быть внутри этого блока.

Здесь нет подкласса для класcа (в отличие от Test::Unit), всё происходит внутри метода describe().

Методы before() и after()

Методы before() и after() похожи на setup() и teardown() в MiniTest.

Они принимают значения :each или :all, чтобы указать будет блок выполняться перед/после каждого теста или один раз перед/после всех тестов.

К примеру, before :all был бы полезен, если вы хотите подключиться к базе данных лишь единожды.

Метод it()

Используется для определения фактических спецификаций/примеров RSpec.

Принимает опциональную строку, описывающую тестируемое поведение.

Пример

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


class Calculator

  attr_reader :name

  def initialize(name)
  	@name = name
  end

  def add(one, two)
  	one - two # скажем, вы допустили ошибку здесь (- вместо +)
  end

  def subtract(one, two)
  	one + two # и в этом методе
  end

  def divide(one, two)
  	one / two
  end
end

Выполним в терминале команду rspec --init в нужной папке, чтобы всё было подготовлено.

spec/calculator_spec.rb:


require 'rspec'
require_relative '../calculator' # или calculator.rb, без разницы

describe Calculator do # здесь вместо класса Calculator можно быть бы написать строку, но здесь это не имеет смысла
  before { @calculator = Calculator.new('RSpec calculator')}

# Фактические спецификации:

  it "should add 2 numbers correctly" do
  	expect(@calculator.add(2, 2)).to eq 4 
  end
  	
  it "should subtract 2 numbers correctly" do
   expect(@calculator.subtract(4, 2)).to eq 2 
  end  

  it "should sum two odd numbers and become even" do
   expect(@calculator.add(3, 3)).to be_even 
   expect(@calculator.add(3, 3)).not_to be_odd 
  end

end

Как мы видим, RSpec более интуитивный и больше похож на естественный английский.

Выполняем команду rspec.

После устранения ошибок результат выполнения теста будет выглядеть так:

В итоге, если вам нравится MiniTest, можете использовать его. Если вам нравится выразительность RSpec, попробуйте это.

Много раз вам придется писать тесты. Некоторые делают это после написания основного кода, некоторые после. Но в целом это довольно важная часть.