Для початку освіжимо пам'ять.
DataMapper - це ORM бібліотека (англ. Object-relational mapping, Обє'ктно-реляційна проекція - технологія, яка зв'язую бази даних з концепцією об'єктно-орієнтовного програмування, створюючи "віртуальну об'єктну базу даних").
Асоціації - це спосіб оголошення відносин між моделями. Вони надають ряд методів, які дозволяють створювати відносини та отримувати пов'язані моделі.
Зараз ORM використовуються повсюдно - ніхто не намагається працювати з базою вручну. Функціонал дозволяє зробити багато речей простіше. Робота з асоціаціями стала в рази легшою. Можна не використовувати SQL-запити, а працювати з даними, як зі звичайними об'єктами.
Я писав цю статтю виключно для себе, тому методика викладання навряд чи сподобається вам своєю легкістю і доступністю :))
Картинка для затравки.
Зацікавило? Тоді ласкаво прошу під кат.
Вхідні дані
- Користувач(Account).
- Подія(Event).
- Коментар(Comment)
- Лайк(Like)
1 асоціація
- Подія має одного користувача(Event.owner => Account)
- Користувач є власником безлічі подій(Account.events => Event)
2 асоціація
- Коментар має одного користувача(Comment.owner => Account)
- Користувач є власником безлічі коментарів(Account.comments => Comment)
3 асоціація
- Подія має безліч коментарів(Event.comments => Comment)
- Коментар належить одній події(Comment.event => Event)
4 асоціація
- Користувач може "лайкати" подію(Account.likeds => Event)
- Подія має безліч лайків(Event.likes => Account)
Моделі та асоціації
Визначаємо моделі для таблиць accounts, events, comments:class Account
include DataMapper::Resource
property :id, Serial
property :name, String
end
class Event
include DataMapper::Resource
property :id, Serial
property :name, String
end
class Comment
include DataMapper::Resource
property :id, Serial
property :body, Text
end
На малюнку нижче приведена схема бази даних, а цифрами позначені асоціації між її таблицями.
Далі по черзі описуємо наші асоціації:
1 асоціація
Подія має одного користувача, а користувач може бути власником безлічі подій.Тут потрібно використовувати зв'язок "один-до-багатьох", який реалізовується через додаткову таблицю authorships.
class Account
include DataMapper::Resource
has n, :authorships
has n, :events, :through => :authorships
end
class Event
include DataMapper::Resource
has n, :authorships
has 1, :owner, :model => 'Account', :through => :authorships, :via => :account
end
class Authorship
include DataMapper::Resource
belongs_to :account, :key => true
belongs_to :event, :key => true
end
Створимо користувача Anton і подію, автором якої буде цей користувач:
account = Account.create(:name => 'Anton')
account.save
event = Event.create(:name => 'Everyone invited!')
event.owner = account
event.save
Події, автором яких є Anton:
account.events.each do |event|
puts "#{event.owner.name}: #{event.name}"
end
2 асоціація
Коментар має одного користувача, а користувач може бути власником безлічі коментарів.Як і у попередній асоціації використовуємо зв'язок "один-до-багатьох", який реалізовується через додаткову таблицю commentators.
class Account
include DataMapper::Resource
has n, :commentators
has n, :comments, :through => :commentators
end
class Comment
include DataMapper::Resource
has n, :commentators
has 1, :owner, :model => 'Account', :through => :commentators, :via => :account
end
class Commentator
include DataMapper::Resource
belongs_to :account, :key => true
belongs_to :comment, :key => true
end
3 асоціація
Подія має безліч коментарів.Тут все просто. Використовуємо зв'язок "один-до-багатьох".
class Event
include DataMapper::Resource
has n, :comments
end
class Comment
include DataMapper::Resource
belongs_to :event
end
Створимо двох користувачів Zoriana та Olia, які прокоментують подію створену користувачем Anton:
guest1 = Account.create(:name => 'Zoriana')
guest1.save
guest2 = Account.create(:name => 'Olia')
guest2.save
comment1 = Comment.create(:body => 'Right here!')
comment1.owner = guest1
event.comments << comment1
comment1.save
comment2 = Comment.create(:body => 'Right now!')
comment2.owner = guest2
event.comments << comment2
comment2.save
Коментарі до події:
event.comments.each do |comment|
puts "#{comment.owner.name}: #{comment.body}"
end
Події, які коментувала Zoriana:
guest1.comments.each{ |comment| puts "#{comment.event.name} - #{comment.body}" }
4 асоціація
Користувач може "лайкати" подію, а подія може мати безліч лайків від користувачів.Тут будемо використовувати зв’язок "багато-до-багатьох", який реалізовується через додаткову таблицю likeables
class Account
include DataMapper::Resource
has n, :likeables
has n, :likeds, :model => 'Event', :through => :likeables, :via => :event
end
class Event
include DataMapper::Resource
has n, :likeables
has n, :likes, :model => 'Account', :through => :likeables, :via => :account
end
class Likeable
include DataMapper::Resource
belongs_to :account, :key => true
belongs_to :event, :key => true
end
Користувачам Anton та Zoriana сподобалась подія:
event.likes << account
event.likes << guest1
event.save
Користувачі, яким сподобалась подія:
event.likes.each{|like| puts like.name}
Події, які сподобалися користувачу Zoriana:
guest1.likeds.each{ |like| puts "#{like.name}" }
Нижче наведений повний код моделей з асоціаціями між ними:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Account | |
include DataMapper::Resource | |
property :id, Serial | |
property :name, String | |
##### | |
# 1 # | |
##### One-to-many-through | |
# Користувач є власником безлічі подій | |
has n, :authorships | |
has n, :events, :through => :authorships | |
### | |
##### | |
# 2 # | |
##### One-to-many-through | |
# Користувач є власником безлічі коментарів | |
has n, :commentators | |
has n, :comments, :through => :commentators | |
### | |
##### | |
# 4 # | |
##### Many-to-many-through | |
# Користувач може "лайкати" подію | |
has n, :likeables | |
has n, :likeds, :model => 'Event', :through => :likeables, :via => :event | |
### | |
end | |
class Event | |
include DataMapper::Resource | |
property :id, Serial | |
property :name, String | |
##### | |
# 1 # | |
##### One-to-many-through | |
# Подія має одного користувача | |
has n, :authorships | |
has 1, :owner, :model => 'Account', :through => :authorships, :via => :account | |
### | |
##### | |
# 3 # | |
##### One-to-many | |
# Подія має безліч коментарів | |
has n, :comments | |
##### | |
# 4 # | |
##### Many-to-many-through | |
# Подія має безліч лайків | |
has n, :likeables | |
has n, :likes, :model => 'Account', :through => :likeables, :via => :account | |
### | |
end | |
class Comment | |
include DataMapper::Resource | |
property :id, Serial | |
property :body, Text | |
##### | |
# 2 # | |
##### One-to-many-through | |
# Коментар має одного користувача | |
has n, :commentators | |
has 1, :owner, :model => 'Account', :through => :commentators, :via => :account | |
### | |
##### | |
# 3 # | |
##### One-to-many | |
# Коментар належить одній події | |
belongs_to :event | |
end | |
##### | |
# 1 # | |
##### One-to-many-through | |
class Authorship | |
include DataMapper::Resource | |
belongs_to :account, :key => true | |
belongs_to :event, :key => true | |
end | |
##### | |
# 2 # | |
##### One-to-many-through | |
class Commentator | |
include DataMapper::Resource | |
belongs_to :account, :key => true | |
belongs_to :comment, :key => true | |
end | |
##### | |
# 4 # | |
##### Many-to-many-through | |
class Likeable | |
include DataMapper::Resource | |
belongs_to :account, :key => true | |
belongs_to :event, :key => true | |
end |
Замість постскриптуму. Офіційна документація про асоціації в DataMapper.
Немає коментарів:
Дописати коментар