ActiveRecord: ORM и типы данных

ActiveRecord and data typesActiveRecord — удивительная библиотека, благодаря которой работа с СУБД становится необычайно лаконичной. Достигается это применением техники ORM (Object-Relational Mapping), шаблона проектирования Active record (Активная запись) и некоторыми другими архитектурными решениями.
Меня сразу заинтересовал вопрос, в чём различия между ORM и шаблоном Active record? Хотя подобные вопросы носят скорее философский характер и не мешают применять библиотеку ActiveRecord на практике, мне всегда хотелось иметь более ясное представление о концепциях и технологиях, которые используются в работе. Поэтому, немного побродив по сети, выяснил, что ORM обладает более широким смыслом. Шаблон Active record призван обеспечить взаимодействие с реляционными базами данных посредством ООП. Таблица представляется в виде класса, строка — в виде объекта, поле (атрибут) — в виде свойства объекта. Для реализации CRUD-операций объект содержит соответствующий набор методов. ORM содержит схожие идеи, но вы не обязательно должны привязываться к реляционной модели данных. Другими словами, ORM является объектным представлением источника данных, в качестве которого могут выступать как реляционные СУБД, так и NoSQL-хранилища данных.
Таким образом, можно сказать, что библиотека ActiveRecord — это ORM, реализующая шаблон Active record для взаимодействия с реляционными базами данных.

Если теперь мы зададимся целью перечислить существующие реляционные СУБД, их количество окажется весьма внушительным. И хотя в их сердце лежит стандарт SQL, каждая СУБД использует свой собственный SQL-диалект. Поскольку ActiveRecord не привязан к какой-то конкретной СУБД, он должен учитывать существующие различия. Это достигается с помощью специального класса — адаптера. Каждый раз, когда мы создаём подключение к базе данных с помощью вызова метода ActiveRecord::Base.establish_connection или указываем конфигурацию для rails-приложения в файле config/database.yml (путь относительно корневого каталога приложения), мы указываем имя адаптера, который будет отвечать за взаимодействие с СУБД. Например так:

ActiveRecord::Base.establish_connection adapter: «mysql2»,
host: «localhost»,
username: «emerald»,
password: «dawn»,
database: «music»
В данном случае адаптер называется mysql2. Это означает, что ActiveRecord будет искать вот такой файл: active_record/connection_apdapters/mysql2_adapter.rb в котором подразумевается определение класса Mysql2Adapter. На самом деле, для каждого имени адаптера необходим соответствующий файл и класс. Некоторые адаптеры по умолчанию уже поставляются вместе с ActiveRecord. Если мы из корневого каталога rails-приложения выполним команду bundle open activerecord (как настроить команду bundle open можно посмотреть здесь) и заглянем в lib/active_record/connection_adapters, то увидим файлы для адаптеров sqlite, sqlite3, postgresql, mysql и mysql2. Другие адаптеры для работы с соответствующими СУБД можно поискать среди gem-ов.

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

* binary
* boolean
* date
* datetime
* decimal
* float
* integer
* primary_key
* string
* text
* time
* timestamp

Обычно их отображение на типы данных СУБД задаётся в виде метода экземпляра адаптера #native_database_types, который возвращает хэш. Этот метод определяется в соответствующем классе адаптера. Например, для mysql2 нужно смотреть класс ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter в файле lib/active_record/connection_adapters/abstract_mysql_adapter.rb. Интересные нам фрагменты кода выглядят так:

[code language=«ruby» gutter=«false» title=«lib/active_record/connection_adapters/abstract_mysql_adapter.rb»]
# Line 113
NATIVE_DATABASE_TYPES = {
:primary_key => «int(11) DEFAULT NULL auto_increment PRIMARY KEY»,
:string => { :name => «varchar», :limit => 255 },
:text => { :name => «text» },
:integer => { :name => «int», :limit => 4 },
:float => { :name => «float» },
:decimal => { :name => «decimal» },
:datetime => { :name => «datetime» },
:timestamp => { :name => «datetime» },
:time => { :name => «time» },
:date => { :name => «date» },
:binary => { :name => «blob» },
:boolean => { :name => «tinyint», :limit => 1 }
}

# Line 173
def native_database_types
NATIVE_DATABASE_TYPES
end
[/code]
В конечном итоге, получить тот же хэш можно непосредственным вызовом метода у объекта адаптера:

ActiveRecord::Base.connection.native_database_types

В общем, если вы вдруг забыли как на самом деле будет выглядеть тип данных boolean в MySQL, вы всегда сможете найти ответ в исходном коде или вызове метода. В Rails 4 — здесь без изменений.

ссылка на оригинал статьи http://habrahabr.ru/post/221499/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *