Ruby — один из самых популярных языков, используемых в сети. Здесь мы начали новую сессию на Nettuts +, которая познакомит вас с Ruby, а также с отличными фреймворками и инструментами, которые сопровождают разработку на Ruby. Сегодня мы рассмотрим гемы DataMapper, чтобы начать работу с базой данных в Ruby.
Предпочитаете видеоурок?
Шаг 0 : Представляем DataMapper
DataMapper — это ORM: объектно-реляционное отображение. По сути, это библиотека, которая позволяет вам работать с вашей базой данных из объектно-ориентированного кода. В этом уроке нет абсолютно никакого SQL. Однако ORM использует обычную базу данных под прикрытием; Сегодня мы будем использовать sqlite3, но вы можете просто использовать другой адаптер для работы с MySQL, PostGresql или другой базой данных.
В « Пении с Синатрой — приложение Recall» Дэн Харпер познакомил вас с DataMapper. В этом уроке мы углубимся в работу с библиотекой.
Шаг 1 : Установка правильных жемчужин
Первый шаг — установка необходимых драгоценных камней. Функциональность DataMapper разбита на множество разных гемов, поэтому вам придется установить несколько разных частей. Конечно, мы не будем работать со всем этим; но это драгоценные камни, которые вы должны будете установить.
- sqlite3 : это драгоценный камень базы данных.
- dm-core : это основная функциональность DataMapper.
- dm-migrations : этот гем выполняет миграцию базы данных.
- dm-validations : как вы уже догадались, это обеспечивает функциональность проверки данных.
- dm-timestamps : помогает с метками времени записей базы данных.
-
dm-sqlite-adapter : это адаптер, который подключает DataMapper к вашей базе данных; здесь мы будем использовать sqlite, но вы можете использовать
dm-postgres-adapter
,dm-mysql-adapter
или все, что вам подходит.
Как только вы установите все эти драгоценные камни (см. Последнюю главу, если вам нужно знать, как установить драгоценные камни ), мы готовы к работе.
Шаг 2 : Создание базовой модели
Давайте начнем с создания базовой модели. Модели определены в классах. Однако сначала мы должны подключиться к нашей базе данных.
На самом деле, самое первое, что нам нужно — это наши библиотеки вверху нашего файла.
1
2
3
4
|
require ‘dm-core’
require ‘dm-timestamps’
require ‘dm-validations’
require ‘dm-migration’
|
Итак, теперь, когда у нас есть DataMapper в среде, давайте подключимся к базе данных.
1
|
DataMapper.setup :default, «sqlite://#{Dir.pwd}/database.db»
|
Первый параметр указывает DataMapper использовать адаптер по умолчанию для типа базы данных. Вторая ссылка / URL для базы данных. Поскольку мы используем sqlite, мы просто ссылаемся на файл базы данных. Обратите внимание, что нам не нужно создавать этот файл; DataMapper создаст его для нас.
Теперь мы готовы создать модель. Как вы знаете, это класс.
1
2
3
4
5
6
7
|
class User
include DataMapper::Resource
property :id , Serial
property :username , String
property :email , String
end
|
Первым шагом является включение модуля DataMapper::Resource
. Это дает вам пользовательские методы, которые вы будете использовать в своем классе. Самый важный метод здесь — это property
. Здесь мы используем его для создания трех разных свойств: идентификатора, имени пользователя и адреса электронной почты. Как видите, первым параметром property
является символ, который является именем свойства. Второй тип. Вы понимаете String, конечно, но что такое серийный. Собственно, property :id, Serial
— сокращение от DataMapper для первичного ключа; ‘serial’ — это автоинкрементное целое число. Это ваш первичный ключ!
Шаг 3 : Миграция базы данных
Теперь, когда мы создали нашу модель, нам нужно перенести базу данных. Если вы не знакомы с миграцией базы данных, это процесс изменения схемы базы данных. Это может быть добавление столбца, переименование столбца или изменение свойств столбца. DataMapper предлагает два способа сделать это:
1
2
|
DataMapper.auto_migrate!
DataMapper.auto_upgrade!
|
Разница здесь в том, что auto_migrate!
очистит все данные из базы данных; auto_upgrade!
методы пытается согласовать то, что уже есть в базе данных, с изменениями, которые вы хотите внести. Это работает так, что после вашего класса модели вы вызовете один из этих методов. Вы не хотите запускать auto_migrate!
Конечно, каждый раз, когда вы загружаете модель, вы можете запустить auto_upgrade!
на каждой перезагрузке в разработке. Я сделал это так в Синатре:
1
2
3
|
configure :development do
DataMapper.auto_upgrade!
end
|
Вы заметите, что до сих пор нам не нужно было трогать ни одного SQL-запроса; смысл использования ORM в том, что вы можете писать нормальный код и работать с реляционными базами данных.
Шаг 4 : Добавление некоторых расширенных атрибутов
Теперь, когда у нас есть ноги с DataMapper, давайте поднимем нашу модель на другой уровень. Давайте начнем с отметок времени.
Timestamps
Нам dm-timestamps
гем dm-timestamps
, так почему бы не использовать его? Если мы добавим в модель свойства «create_at» и «updated_at», этот гем автоматически обновит эти поля.
свойство: made_at, DateTime свойство: updated_at, DateTime
Конечно, вам не нужно добавлять оба, если вы не хотите их.
Параметры
Есть несколько опций, которые вы можете добавить в каждое поле. Например, если вы хотите, чтобы поле было обязательным, уникальным или имело значение по умолчанию, вы можете сделать это там. Давайте создадим модель поста, чтобы продемонстрировать некоторые из них:
1
2
3
4
5
6
7
8
9
|
class Post
include DataMapper::Resource
property :slug , String , key: true, unique_index: true, default: lambda { |resource,prop|
property :title , String , required: true
property :body , Text , required: true
property :created_at , DateTime
property :updated_at , DateTime
end
|
Мы здесь немного перемешиваем; наши ‘title’ и ‘body’ являются обязательными полями. Мы определяем свойство ‘slug’ в качестве первичного ключа и говорим, что это должен быть уникальный индекс. Не пугайтесь значения по умолчанию ‘slug.’ Конечно, вы можете просто использовать необработанное значение любого типа, которым принадлежит ваша собственность, но мы делаем что-то большее. В Ruby (и других языках) есть лямбды, о которых вы можете думать как о маленькой функции. Это то, что может принимать «параметры» и возвращать значение, как функция. Если мы используем лямбду в качестве значения свойства ‘default’, DataMapper передаст ему ресурс (или запись базы данных, с которой вы работаете) и само свойство (в данном случае, ‘slug’). Итак, здесь мы берем значение в resource.title
(свойство title), помещаем его в нижний регистр и используем метод gsub
( например, g gobal), чтобы переключить каждый пробел на тире. Таким образом, что-то вроде этого:
1
|
«This is a Title»
|
Станет так:
1
|
«this-is-a-title»
|
Примечание: не запутайтесь в том, как мы используем параметры здесь. Прежде всего, помните, что когда хеш является последним параметром метода, нам не нужно добавлять фигурные скобки. Кроме того, в Ruby 1.9 появился новый синтаксис хэша. Ранее хэши выглядели так:
1
|
{ :key => «value» }
|
Вы все еще можете сделать это в 1.9, и вам это нужно, если вы не используете символы в качестве ключей. Но, если вы используете символы в качестве ключей, вы можете сделать это вместо этого:
1
|
{ key: «value» }
|
По сути, вы просто перемещаете двоеточие до конца символа (без пробела!) И удаляете ракету.
Validations
В DataMapper вы можете многое сделать с проверкой, и вы можете прочитать все об этом здесь . Тем не менее, давайте посмотрим на основы.
Есть два способа сделать проверки; мы собираемся использовать метод, который добавляет ваши проверки в хэш опций. Для свойства email в модели User мы установим проверку формата:
1
|
property :email, String, format: :email_address
|
В этом случае мы используем встроенное регулярное выражение, которое предлагает DataMapper; мы могли бы поместить пользовательское регулярное выражение там, если бы мы хотели что-то еще.
Давайте потребуем определенную длину пароля:
1
|
property :password, String, length: 10..255
|
Если вы не знакомы с обозначением 10..255, это диапазон Ruby. Мы говорим, что пароль должен быть длиной от 10 до 255 символов.
ассоциации
Как насчет внешних ключей? DataMapper делает это действительно легко. Давайте свяжем наши модели User и Post. Мы хотим, чтобы у пользователя было много постов, а пост должен принадлежать пользователю.
В модели User добавьте эту строку
1
|
has n, :posts
|
Затем, в модели Post, сделайте это:
1
|
belongs_to :user
|
В базе данных это добавляет свойство user_id
к таблице user_id
. На практике это действительно легко; мы увидим это в ближайшее время.
Средства доступа к пользовательским свойствам
Если вы хотите настроить ввод для данного свойства, вы можете добавить собственные средства доступа к свойствам. Например, допустим, мы хотим убедиться, что имя пользователя пользователя всегда хранится в нижнем регистре. Мы можем добавить методы доступа к свойствам так же, как в обычном классе. Таким образом, мы берем значение, которое пользователь пытается сохранить, и исправляем его. Давай сделаем это:
1
2
3
|
def username= new_username
super new_username.downcase
end
|
Мы определяем username=
, поэтому, когда имя пользователя назначается, оно будет в нижнем регистре. super
часть просто передает наше значение супер-методу этого метода, который мы переопределяем.
Примечание. Согласно документации (см. Здесь и здесь ), мы должны иметь возможность сделать @username = new_username.downcase
в методе выше. Это то, что я сделал в скриншоте, и, как вы знаете, это не сработало, как ожидалось. С момента записи скриншота я обнаружил, что документация неверна, и это super
способ сделать это .
Шаг 5 : Создание и поиск записей
Итак, теперь, когда наши модели созданы, давайте добавим несколько записей, чтобы проверить их. Мы можем сделать это несколькими способами. Во-первых, мы можем создать запись с помощью new
метода, передавая хэш атрибутов или назначая их по отдельности.
1
2
3
4
5
6
7
|
user = User.new username: «JoeSchmo», firstname: «Joe», lastname: «Schmo», email: «[email protected]», password: «password_12345»
user.save
user = User.new
user.username = «Andrew»
# etc.
user.save
|
При использовании User#new
необходимо вызвать метод save
чтобы фактически поместить запись в базу данных. Если есть ошибка (помните эти проверки?), Метод save
вернет false. Затем вы можете перейти к свойству errors
чтобы увидеть ошибки; это объект DataMapper :: Validations :: ValidationsErrors, но вы можете перебирать ошибки с each
методом.
1
2
3
|
user.errors.each do |error|
puts error
end
|
Если вы хотите сделать и сохранить запись одним махом, используйте метод create
, конечно, передав ему хэш атрибутов.
1
|
User.create username: «joeschmo», firstname: «Joe», lastname: «Schmo», email: «[email protected]», password: «password_!@#$%»
|
Бум: создан и сохранен!
Как насчет поиска записи в базе данных? Если вы знаете ключ нужной записи, просто используйте метод get:
1
2
3
|
User.get(1)
Post.get(«this-is-a-title»)
|
Да, вы видите, что это работает как с обычными целочисленными ключами, так и с другими типами ключей. Поскольку мы сказали, что слизняк является ключом в модели Post
, мы можем get
слаг.
А как насчет тех полей, которые могут быть одинаковыми для нескольких записей? У вас есть три варианта для этого: первый, последний и все. Просто передайте им хеш, и они получат записи для вас
1
2
3
4
5
|
User.first firstname: «Andrew»
User.last( :lastname => «Schmo»)
User.all #gets all the post
|
Вывод: учимся больше
С DataMapper вы можете сделать гораздо больше; проверьте документацию для больше! Нажмите на поле с вопросом, если у вас есть какие-либо вопросы.