...

среда, 30 апреля 2014 г.

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 — здесь без изменений.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий