База данных — загадочное, но могущественное существо

Лондон, Шордич

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

Цель на эту неделю довольно проста.

  • Объяснить основы работы баз данных (например, SQL, сопоставление моделей отношений сущностей, сопоставление отношений объектов и т. д.)
  • Создайте простое веб-приложение с базой данных(На неделе мы создали менеджер закладок, на выходных это был Chitter Challenge — упрощенная версия Twitter; также важно принять и внедрить дизайн маршрута RESTful. также)
  • Другое (понимать, что такое переменные env и как их настраивать на разных этапах разработки; изучать и применять немного синтаксического сахара ruby)

Первая часть посвящена основам базы данных (базы данных отношений). Поскольку я узнал о SQL ранее, мне было удобно манипулировать языком для создания и изменения таблицы. Однако, когда дело доходит до сопоставления объектных отношений, это другое дело.

Давайте вернемся к этой концепции. Согласно Википедии, суть проблемы заключается в преобразовании логического представления объектов в атомарную форму, которую можно хранить в базе данных, сохраняя при этом свойства объектов и их отношения, чтобы при необходимости их можно перезагрузить как объекты. Если эта функция хранения и поиска реализована, объекты называются постоянными.

Я предполагаю, что причина, по которой я чувствовал себя сложно на этой неделе, была связана с тем, что мы интегрировали базу данных в модель MVC в учебном плане — то есть преобразование данных SQL в Object в Ruby.

Несмотря на то, что мы знаем, что в конечном итоге все мы будем использовать инструменты сопоставления объектных отношений, такие как ActiveRecord или Data Mapper, было бы здорово узнать, как именно это преобразование происходит за кулисами. Таким образом, вместо того, чтобы перейти к легкому жизненному режиму — системам отображения отношений объектов (ORM) в начале, мы сами создали ORM. (Пример ниже :)

def self.create(link, title )
   if ENV[‘RACK_ENV’] == ‘test’
   connection = PG.connect(dbname:’bookmark_manager’)
   else
   connection = PG.connect(dbname:’bookmark_manager_test’)
   end
   result = connection.exec(“INSERT INTO bookmarks(url, title) VALUES (‘#{link}’,’#{title}’) RETURNING id, url, title;”)
   Bookmarks.new(id: result[0][‘id’], title: result[0][‘title’], url: result[0][‘url’])
end 

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

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

  • Перенести данные базы данных из строк базы данных в приложение Ruby.
  • Заключите эти данные в объекты Ruby.
  • Попросите модель сделать что-нибудь с данными, которые она упаковывает.

Еще одна интересная тема, на которую стоит обратить внимание, — это связь между таблицами. В рубине у нас есть 6 основных ассоциаций.

  • belongs_to
  • has_one
  • has_many
  • has_many :through
  • has_one :through
  • has_and_belongs_to_many

Вы можете заметить, что может быть несколько вариантов соединения таблиц. Например, у вас может быть либо has_many :through, либо has_and_belongs_to_many, чтобы связать таблицу A с таблицей B через таблицу B, или сделать таблицу C основной сущностью, которая имеет связь с таблицей B и принадлежит таблице A.

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

Например, тесты всегда должны выполняться для пустой базы данных. Мы должны настроить все необходимые тестовые данные в самом тесте. Чтобы сделать тесты независимыми друг от друга, нам нужно настраивать и очищать тестовую базу данных при каждом запуске. Один из способов сделать это — «сбрасывать» базу данных между каждым запуском скрипта:

# in spec/setup_test_database.rb
def setup_test_database
connection = PG.connect(dbname: 'bookmark_manager_test')
  connection.exec("TRUNCATE bookmarks;")
end

Используя таблицу TRUNCATE, этот подход очищает данные из таблицы bookmarks.

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

Одна интересная концепция — обязательные аргументы ключевого слова, которые определяются двоеточием в конце. Как необычный способ определения методов, аргументы с ключевыми словами имеют свои плюсы и минусы:

Допустим, у нас есть метод для расчета конечной цены продукта:

def mysterious_total(subtotal, tax, discount)
  subtotal + tax - discount
end
mysterious_total(100, 10, 5) # => 105

Этот метод выполняет свою работу, но как читатель кода, использующего метод mysterious_total, вы понятия не имеете, что означают эти аргументы, не посмотрев реализацию метода. Используя аргументы ключевого слова, мы знаем, что означают аргументы, не просматривая реализацию вызываемого метода:

def obvious_total(subtotal:, tax:, discount:)
  subtotal + tax - discount
end
obvious_total(subtotal: 100, tax: 10, discount: 5) # => 105

Таким образом, аргументы ключевого слова позволяют нам переключать порядок аргументов, не влияя на поведение метода:

obvious_total(subtotal: 100, discount: 5, tax: 10) # => 105

Если мы изменим порядок позиционных аргументов, мы не получим тех же результатов, предоставив нашим клиентам большую скидку, чем они того заслуживают:

mysterious_total(100, 5, 10) # => 95

Это все на этой неделе. Увидимся на следующей неделе:)

==========Главные события недели==============

А. Основы базы данных

SQL

SQL (произносится как «ess-que-el») означает язык структурированных запросов. SQL используется для связи с базой данных. Это стандартный язык для систем управления реляционными базами данных. Операторы SQL используются для выполнения таких задач, как обновление данных в базе данных или извлечение данных из базы данных.

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

Внешний ключ.Внешний ключ — это поле в реляционной таблице, которое соответствует столбцу первичного ключа другой таблицы. Он связывает два ключа. Внешние ключи не обязательно должны иметь уникальные значения в отношении ссылки. Внешний ключ можно использовать для перекрестных ссылок на таблицы, и он эффективно использует значения атрибутов в отношении, на которое делается ссылка, для ограничения домена одного или нескольких атрибутов в отношении, на которое делается ссылка. Формально эта концепция описывается следующим образом: «Для всех кортежей в ссылочном отношении, спроецированном на ссылочные атрибуты, должен существовать кортеж в ссылочном отношении, спроецированном на те же самые атрибуты, так что значения в каждом из ссылочных атрибутов совпадают с соответствующими значениями в ссылочном атрибуте. упомянутые атрибуты».

Ассоциация моделей отношений сущностей

Rails поддерживает шесть типов ассоциаций:

  • belongs_to
  • has_one
  • has_many
  • has_many :through
  • has_one :through
  • has_and_belongs_to_many

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

Общая команда PostgreSQL:

CREATE TABLE bookmarks(id SERIAL PRIMARY KEY, url VARCHAR(60));
INSERT INTO bookmarks (url) VALUES ('http://www.makersacademy.com');
SELECT * FROM bookmarks WHERE url = 'http://www.makersacademy.com';
DELETE FROM bookmarks WHERE url = 'http://www.twitter.com';
UPDATE bookmarks SET url = 'http://www.destroyallsoftware.com' WHERE url = 'http://www.askjeeves.com';
DROP TABLE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ];
TRUNCATE [ TABLE ] name [, ...] [ CASCADE | RESTRICT ]
INSERT INTO users (firstname, lastname) VALUES ('Joe', 'Cool') RETURNING id;

DROP TABLE удаляет таблицу.

TRUNCATE TABLE очищает его, но оставляет его структуру для будущих данных

Рубин PG Драгоценный камень

Ruby pg — это модуль, который позволяет программам Ruby взаимодействовать с ядром базы данных PostgreSQL. Он поддерживает функции, определенные в libpq библиотеке C.

Объектно-реляционное отображение

Согласно Википедии (ORM, O/RM и инструмент сопоставления O/R) в информатике — это метод программирования для преобразования данных между несовместимые системы типов, использующие объектно-ориентированные языки программирования.

В объектно-ориентированном программировании задачи управления данными воздействуют на объекты, которые почти всегда являются нескалярными значениями. Например, запись адресной книги, представляющая одного человека, а также ноль или более телефонных номеров и ноль или более адресов. Это может быть смоделировано в объектно-ориентированной реализации с помощью «объекта Person» с атрибутами/полями для хранения каждого элемента данных, который содержит запись. С объектом могут быть связаны различные методы, такие как метод возврата предпочтительного номера телефона, домашнего адреса и т. д.

Однако многие популярные продукты баз данных, такие как системы управления базами данных SQL (СУБД), могут хранить и обрабатывать только скалярные значения, такие как целые числа и строки, организованные в таблицах. Программист должен либо преобразовать значения объекта в группы более простых значений для хранения в базе данных (и преобразовать их обратно при извлечении), либо использовать в программе только простые скалярные значения. Объектно-реляционное отображение реализует первый подход.

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

ORM расшифровывается как «Object to Relational Mapping», где

  • Часть Object — это та часть, которую вы используете с вашим языком программирования (в данном случае Python).
  • Реляционная часть — это система управления реляционной базой данных (база данных). Существуют и другие типы баз данных, но наиболее популярными являются реляционные (вы знаете, таблицы, столбцы, pk fk и т. д., например, Oracle MySQL, MS- SQL
  • И, наконец, в части Mapping вы создаете мост между вашими объектами и вашими таблицами.

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

В ruby ​​есть два популярных инструмента ORM: активная запись и сопоставитель данных.

B. Настройте надлежащую среду

Что такое ЭНВ

Env vars легко изменить между развертываниями без изменения кода; в отличие от конфигурационных файлов, вероятность того, что они случайно попадут в репозиторий кода, мала; и в отличие от пользовательских файлов конфигурации или других механизмов конфигурации, таких как свойства системы Java, они являются стандартом, не зависящим от языка и ОС. По словам Старр Хорн:

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

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

Наличие нескольких сред в приложениях — это нормально. К ним могут относиться:

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

Для данных,

  • Производственная база данных будет содержать «реальные» данные. Например: производственная среда Facebook содержит реальных пользователей, посты, комментарии, лайки и т. д.
  • База данных test не будет содержать данных. Таким образом, мы можем настроить любые данные, которые нам нужны, прямо перед запуском наших тестов.
  • База данных разработки изначально не будет содержать данных. Если мы запустим наше приложение локально, мы сможем добавить в него данные.

C. REST-маршрут

Ресурсы. Интернет — это сеть ресурсов. Ресурс - это некоторые данные, хранящиеся где-то.

Представления Представления связывают URL-адреса с действиями, которые пользователь может захотеть выполнить с этими ресурсами. Например. GET /bookmarks/1

Веб-приложения — это конечные автоматы, и REST определяет их интерфейс.

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

  • Наличие 35 закладок (состояние)
  • Добавление закладки (переход состояния)

Для каждого из них маршрут RESTful определяет следующее состояние машины, и машина отвечает состоянием, в котором она находится сейчас:

  • GET /bookmarks возвращает веб-страницу с 35 закладками
  • POST /bookmarks переводит машину в новое состояние с 36 закладками и возвращает веб-страницу с 36 закладками.

RESTful-маршрут – это маршрут, обеспечивающий сопоставление между HTTP-глаголами (получить, опубликовать, поместить, удалить, исправить) и действиями контроллера CRUD (создать, прочитать, обновить, удалить). Вместо того, чтобы полагаться исключительно на URL-адрес, чтобы указать, какой сайт посетить, маршрут RESTful также зависит от глагола HTTP и URL-адреса.

Важно отметить, что большая часть действий CRUD — это разные действия, происходящие с одним и тем же ресурсом. Возьмем в качестве примера статью с идентификатором 4. Если бы мы хотели просмотреть статью, мы бы сделали запрос GET к /articles/4. Но что если я захочу обновить эту статью? Я попал на другой ресурс? Неа! Просто выполните другое действие с тем же ресурсом. Поэтому вместо GET против /articles/4 мы делаем PUT. Вот почему так важно отделять то, с чем вы разговариваете (ресурс/существительное), от действия, которое вы делаете (HTTP-глагол)! Это ключ к REST.

D. Сахар синтаксиса Ruby

Аргументы ключевого слова Ruby 2

Обязательные аргументы ключевых слов.Ruby 2.0 не имеет встроенной поддержки обязательных аргументов ключевых слов. К счастью, в Ruby 2.1 появились обязательные аргументы с ключевыми словами, которые определяются двоеточием в конце:

def foo(bar:)
  puts bar
end
foo # => ArgumentError: missing keyword: bar
foo(bar: 'baz') # => 'baz'

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

Аргументы ключевых слов и позиционные аргументы. Предположим, у нас есть метод с позиционными аргументами:

def mysterious_total(subtotal, tax, discount)
  subtotal + tax - discount
end
mysterious_total(100, 10, 5) # => 105

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

Используя аргументы ключевого слова, мы знаем, что означают аргументы, не просматривая реализацию вызываемого метода:

def obvious_total(subtotal:, tax:, discount:)
  subtotal + tax - discount
end
obvious_total(subtotal: 100, tax: 10, discount: 5) # => 105

Аргументы ключевого слова позволяют нам переключать порядок аргументов, не влияя на поведение метода:

obvious_total(subtotal: 100, discount: 5, tax: 10) # => 105

Если мы изменим порядок позиционных аргументов, мы не получим тех же результатов, предоставив нашим клиентам большую скидку, чем они того заслуживают:

mysterious_total(100, 5, 10) # => 95

Неявное назначение массива

Вы можете неявно создать массив, перечислив несколько значений при назначении:

a = 1, 2, 3
p a # prints [1, 2, 3]

Это неявно создает массив.

Вы можете использовать * или оператор «splat» или распаковать массив при назначении. Это похоже на множественное присваивание:

a = *[1, 2, 3]
p a # prints [1, 2, 3]

Вы можете поставить знак в любом месте в левой части задания:

a = 1, *[2, 3]
p a # prints [1, 2, 3]