3. ORM vs. Recordset
• ORM (O/RM) — Object-Relational Mapping.
Отображение реляций БД на ООП-сущности
(классы, объекты, методы). Фактически
создается виртуальная объектная БД
users.first.login
• Recordset — доступ к результату запроса
через хеш, массив или их комбинацию
db[‘users’][0][‘login’]
4. Object Query vs. Raw SQL
• Object Query — генерация
запроса к БД, посредством вызова
методов
User.find(:all, :conditions => {:active => true})
• Raw SQL — использование
чистого SQL для доступа к БД
User.find_by_sql(‘select * from users’)
6. Пример из реального мира
SELECT fc.fieldvalue AS category, fs.fieldvalue AS ticket_type, u.fullname as username,
t.isphonecall AS phone, t.isemailed AS email, coalesce((CASE WHEN fp.fieldvalue IS NULL OR
t.isphonecall = 1 THEN 0 ELSE 1 END), 0) AS web, l.actionmsg AS action_text, t.ticketid as
ticket_id
FROM swtickets t
LEFT JOIN swcustomfieldvalues fc
ON fc.typeid = t.ticketid AND fc.customfieldid = 23
LEFT JOIN swcustomfieldvalues fs
ON fs.typeid = t.ticketid AND fs.customfieldid = 24
INNER JOIN swusers u ON u.userid = t.userid
LEFT JOIN swauditlogs l
ON l.ticketid = t.ticketid
AND l.second_line = 1
LEFT JOIN swcustomfieldvalues fp
ON fp.typeid = t.ticketid AND fp.customfieldid = 26
WHERE t.ticketstatusid IN ? AND FROM_UNIXTIME(t.lastactivity) BETWEEN
DATE(?) AND DATE(?)
ORDER BY t.ticketid, l.dateline DESC
7. Реализация с помощью
ActiveRecord
Swticket.find(:all, :select => ‘fc.fieldvalue AS category, fs.fieldvalue AS ticket_type, u.fullname as
username, t.isphonecall AS phone, t.isemailed AS email, coalesce((CASE WHEN fp.fieldvalue IS
NULL OR t.isphonecall = 1 THEN 0 ELSE 1 END), 0) AS web, l.actionmsg AS action_text,
t.ticketid as ticket_id’,
:joins =>
[‘LEFT JOIN swcustomfieldvalues fc ON fc.typeid = t.ticketid AND fc.customfieldid = 23’,
‘LEFT JOIN swcustomfieldvalues fs ON fs.typeid = t.ticketid AND fs.customfieldid = 24’,
‘INNER JOIN swusers u ON u.userid = t.userid’,
‘LEFT JOIN swauditlogs l ON l.ticketid = t.ticketid AND l.second_line = 1’,
‘LEFT JOIN swcustomfieldvalues fp ON fp.typeid = t.ticketid AND fp.customfieldid = 26’],
:conditions =>
[
‘t.ticketstatusid IN ? AND from_unixtime(t.lastactivity) BETWEEN DATE(?) AND DATE(?)’,
25, 3.days.ago, Date.today
],
:order => ‘t.ticketid, l.dateline DESC’)
13. Модели
• class Post < Sequel::Model
• post = Post[123]
post = Post[:title => ‘Hello’]
• post.title #=> ‘Hello’
post[:title] #=> ‘Hello’
• many_to_one :author
one_to_many :comments
many_to_many :tags
• subset(:posts_with_few_comments){num_comments < 30}
• Валидация, callbacks, бизнес-логика для датасета, STI, миграции, timestamps
и т.д.
14. Чистый SQL
• DB.fetch("SELECT * FROM albums WHERE name LIKE :pattern", :pattern=>'A%') do |row|
puts row[:name]
end
• DB["UPDATE albums SET name = ? WHERE name = ?", 'MO', 'RF'].update
• DB.run "CREATE TABLE albums (id integer primary key, name varchar(255))"
• DB << "ALTER TABLE albums ADD COLUMN copies_sold INTEGER"
• DB[:albums].select{function(col1, col2)} # SELECT function("col1", "col2") FROM "albums"
15. Сравнение с
DataMapper
• DataMapper — только ORM
• Даже в ORM другая философия: DM
модель > БД, Sequel БД > модель
• В Sequel больше back-ends из коробки