· 8 years ago · Mar 12, 2018, 07:56 PM
1files = %w{ scoping relationship has_one has_many join_table }
2dir = File.join(File.dirname(__FILE__), "relationships")
3files.each {|f| require(File.join(dir, f))}
4
5# = Sequel Relationships
6# Database modelling is generally done with an ER (Entity Relationship) diagram.
7# Shouldn't ORM's facilitate simlilar specification?
8
9# class Post < Sequel::Model
10# # Specify the relationships that exist with the User model (users table)
11# # These relationships are precisely the ER diagram connecting arrows.
12# end
13
14#
15# = Relationships
16#
17# are specifications of the ends of the ER diagrams connectors that are touching
18# the current model.
19#
20# one_to_one, has_one
21# many_to_one, belongs_to
22# many_to_many, has_many
23
24# ?parameters may be :zero, :one, :many which specifies the cardinality of the connection
25
26# Example:
27# class Post < Sequel::Model
28# has :one, :blog, :required => true, :normalized => false # uses a blog_id field, which cannot be null, in the Post model
29# has :one, :account # uses a join table called accounts_posts to link the post with it's account.
30# has :many, :comments # uses a comments_posts join table
31# has :many, :authors, :required => true # authors_posts join table, requires at least one author
32# end
33#
34#
35# Relationship API Details
36#
37
38#
39# == belongs_to
40#
41
42# Defines an blog and blog= method
43# belongs_to :blog
44
45# Same, but uses "b_id" as the blog's id field.
46# belongs_to :blog, :key => :b_id
47
48# has_many :comments
49# * Defines comments method which will query the join table appropriately.
50# * Checks to see if a "comments_posts" join table exists (alphabetical order)
51# ** If it does not exist, will create the join table.
52# ** If options are passed in these will be used to further define the join table.
53
54
55# Benefits:
56# * Normalized DB
57# * Easy to define join objects
58# * Efficient queries, database gets to use indexed fields (pkeys) instead of a string field and an id.
59#
60# For example, polymorphic associations now become:
61# [user] 1-* [addresses_users] *-1 [addresses]
62# [companies] 1-* [addresses_companies] *-1 [addresses]
63# [clients] 1-* [addresses_clients] *-1 [addresses]
64# it is automatically polymorphic by specifying the has relationship inside the 2User and Company tables to addresses. Addresses themselves don't care. so we have by default polymorphism.
65# If you need to talk about a 'Company Address' then you can subclass, CompanyAddress < Address and do has :many, :company_addresses
66
67module Sequel
68
69 class Model
70 @relationships = []
71 class << self
72 # has arity<Symbol>, model<Symbol>
73 # has :one, :blog, :required => true # blog_id field, cannot be null
74 # has :one, :account # account_id field
75 # has :many, :comments # comments_posts join table
76 # has :many, :comment # comments_posts join table
77 def has(arity, relation, options = {})
78 # Create and store the relationship
79 case arity
80 when :one
81 @relationships << HasOne.new(self, relation, options)
82 when :many
83 @relationships << HasMany.new(self, relation, options)
84 else
85 raise Sequel::Error, "Arity must be specified {:one, :many}."
86 end
87
88 #unless normalized
89 # :required => true # The relationship must be populated to save
90 # can only be used with normalized => false :
91 #end
92 # save the relationship
93 end
94
95 # the proxy methods has_xxx ... , simply pass thru to to has :xxx, ...
96 def has_one(relation, options = {})
97 has :one, relation, options
98 end
99
100 def has_many(relation, options = {})
101 has :many, relation, options
102 end
103
104 def belongs_to(relation, options = {})
105 @relationships << BelongsTo.new(self, relation, options)
106 end
107
108 #def primary_key_string
109 # "#{self.to_s.tableize.singularize}_id"
110 #end
111
112 end
113
114 end # Model
115
116end # Sequel