sequel-table_inheritance 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.rdoc +11 -181
- data/lib/sequel/plugins/hybrid_table_inheritance.rb +28 -28
- data/sequel-table_inheritance.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b67c3763d27dc1f170724e94da63e7e2ba40c3ab
|
4
|
+
data.tar.gz: be5bec3b9d2c7a035d115d0f6fa7eecff47b0888
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec03d9e27d385a094c8967574bd70eb6c63861ea6a830d49715ec3f2feda6f4bbf2c40b5aaf5f7526afcecb7f41f7e09c01c3c00df62291a9bb5b5265f67a4fe
|
7
|
+
data.tar.gz: d84fd765d8c69354de64d0a7f06bae564c59b041559ee5a701a35cdb9aa3ebd9c47d2da0c947e598e85b734769361ee11dfa336dcf0e276b943732ffca326e01
|
data/README.rdoc
CHANGED
@@ -2,198 +2,28 @@
|
|
2
2
|
|
3
3
|
This is a sequel plugin that combines the functionality of the single and class
|
4
4
|
table inheritance plugins. This plugin uses the single_table_inheritance plugin
|
5
|
-
and should work as a drop in replacement for the class_table_inheritance
|
5
|
+
and should work as a drop in replacement for the class_table_inheritance plugin.
|
6
6
|
This allows using new tables for subclasses only when need for additional columns
|
7
7
|
or possibly referential integrity to exclusively subclassed rows.
|
8
8
|
|
9
9
|
== Additional features over the class table inheritance plugin
|
10
10
|
For class table inheritance use this provides additional functionality beyond
|
11
|
-
the standard
|
11
|
+
the standard class_table_inheritance plugin including the following:
|
12
12
|
|
13
|
-
* Eager loading in addition to lazy loading of subclasses
|
13
|
+
* Eager loading in addition to lazy loading of subclasses.
|
14
14
|
* Use RETURNING * on insert if available avoiding a select query after new model saves
|
15
|
-
* Features found in the
|
15
|
+
* Features found in the single_table_inheritance not in class_table_inheritance
|
16
16
|
Notably the key_map, key_chooser options and accepting a proc in addition to
|
17
17
|
a hash for model_map option
|
18
18
|
|
19
|
-
==
|
20
|
-
=== Overview
|
19
|
+
== Using sequel-table_inheritance
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
referencing the parent table.
|
25
|
-
This combines the functionality of single and class (multiple) table inheritance
|
26
|
-
into one plugin. This plugin uses the single_table_inheritance plugin
|
27
|
-
and should work as a drop in replacement for the class_table_inheritance plugins.
|
28
|
-
This allows introducing new tables only when needed typically for additional
|
29
|
-
fields or possibly referential integrity to subclassed objects.
|
21
|
+
Include the sequel-hybrid_table gem in your Gemfile
|
22
|
+
gem "sequel-table_inheritance"
|
30
23
|
|
31
|
-
|
24
|
+
run "bundle install" if needed
|
32
25
|
|
33
|
-
|
26
|
+
The hybrid_table_inheritance plugin should now work like any other sequel plugin.
|
27
|
+
You should be able to use in place of the class_table_inheritance plugin.
|
34
28
|
|
35
|
-
|
36
|
-
/ \
|
37
|
-
Staff Manager
|
38
|
-
| |
|
39
|
-
Cook Executive
|
40
|
-
|
|
41
|
-
CEO
|
42
|
-
|
43
|
-
the following database schema may be used (table - columns):
|
44
|
-
|
45
|
-
employees :: id, name, kind
|
46
|
-
staff :: id, manager_id
|
47
|
-
managers :: id, num_staff
|
48
|
-
executives :: id, num_managers
|
49
|
-
|
50
|
-
The hybrid_table_inheritance plugin assumes that the root table
|
51
|
-
(e.g. employees) has a primary key field (usually autoincrementing),
|
52
|
-
and all other tables have a foreign key of the same name that points
|
53
|
-
to the same key in their superclass's table. In this example,
|
54
|
-
the employees id column is a primary key and the id column in every
|
55
|
-
other table is a foreign key referencing the employees id.
|
56
|
-
|
57
|
-
In this example the employees table stores Staff model objects and the
|
58
|
-
executives table stores CEO model objects.
|
59
|
-
|
60
|
-
When using the class_table_inheritance plugin, subclasses use joined
|
61
|
-
datasets:
|
62
|
-
|
63
|
-
Employee.dataset.sql
|
64
|
-
# SELECT * FROM employees
|
65
|
-
|
66
|
-
Manager.dataset.sql
|
67
|
-
# SELECT employees.id, employees.name, employees.kind,
|
68
|
-
# managers.num_staff
|
69
|
-
# FROM employees
|
70
|
-
# JOIN managers ON (managers.id = employees.id)
|
71
|
-
|
72
|
-
CEO.dataset.sql
|
73
|
-
# SELECT employees.id, employees.name, employees.kind,
|
74
|
-
# managers.num_staff, executives.num_managers
|
75
|
-
# FROM employees
|
76
|
-
# JOIN managers ON (managers.id = employees.id)
|
77
|
-
# JOIN executives ON (executives.id = managers.id)
|
78
|
-
# WHERE (employees.kind IN ('CEO'))
|
79
|
-
|
80
|
-
This allows CEO.all to return instances with all attributes
|
81
|
-
loaded. The plugin overrides the deleting, inserting, and updating
|
82
|
-
in the model to work with multiple tables, by handling each table
|
83
|
-
individually.
|
84
|
-
|
85
|
-
=== Subclass loading
|
86
|
-
|
87
|
-
When model objects are retrieved for a superclass the result could be
|
88
|
-
subclass objects needing additional attributes from other tables.
|
89
|
-
This plugin can load those additional attributes immediately with eager
|
90
|
-
loading or when requested on the object with lazy loading.
|
91
|
-
|
92
|
-
With eager loading, the additional needed rows will be loaded with the
|
93
|
-
all or first methods. Note that eager loading does not work
|
94
|
-
with the each method because all of the records must be loaded to
|
95
|
-
determine the keys for each subclass query. In that case lazy loading can
|
96
|
-
be used or the each method used on the result of the all method.
|
97
|
-
|
98
|
-
If lazy loading is used the lazy_attributes plugin will be included to
|
99
|
-
return subclass specific attributes that were not loaded
|
100
|
-
when calling superclass methods (since those wouldn't join
|
101
|
-
to the subclass tables). For example:
|
102
|
-
|
103
|
-
a = Employee.all # [<#Staff>, <#Manager>, <#Executive>]
|
104
|
-
a.first.values # {:id=>1, name=>'S', :kind=>'Staff'}
|
105
|
-
a.first.manager_id # Loads the manager_id attribute from the database
|
106
|
-
|
107
|
-
If you want to get all columns in a subclass instance after loading
|
108
|
-
via the superclass, call Model#refresh.
|
109
|
-
|
110
|
-
a = Employee.first
|
111
|
-
a.values # {:id=>1, name=>'S', :kind=>'CEO'}
|
112
|
-
a.refresh.values # {:id=>1, name=>'S', :kind=>'Executive', :num_staff=>4, :num_managers=>2}
|
113
|
-
|
114
|
-
The option :subclass_load sets the default subclass loading strategy.
|
115
|
-
It accepts :eager, :eager_only, :lazy or :lazy_only with a default of :lazy
|
116
|
-
The _only options will only allow that strategy to be used.
|
117
|
-
In addition eager or lazy can be called on a dataset to override the default
|
118
|
-
strategy used assuming an _only option was not set.
|
119
|
-
|
120
|
-
=== Usage
|
121
|
-
|
122
|
-
# Use the default of storing the class name in the sti_key
|
123
|
-
# column (:kind in this case)
|
124
|
-
class Employee < Sequel::Model
|
125
|
-
plugin :hybrid_table_inheritance, :key=>:kind
|
126
|
-
end
|
127
|
-
|
128
|
-
# Have subclasses inherit from the appropriate class
|
129
|
-
class Staff < Employee; end # uses staff table
|
130
|
-
class Cook < Staff; end # cooks table doesn't exist so uses staff table
|
131
|
-
class Manager < Employee; end # uses managers table
|
132
|
-
class Executive < Manager; end # uses executives table
|
133
|
-
class CEO < Executive; end # ceos table doesn't exist so uses executives table
|
134
|
-
|
135
|
-
# Some examples of using these options:
|
136
|
-
|
137
|
-
# Specifying the tables with a :table_map hash
|
138
|
-
Employee.plugin :hybrid_table_inheritance,
|
139
|
-
:table_map=>{:Employee => :employees,
|
140
|
-
:Staff => :staff,
|
141
|
-
:Cook => :staff,
|
142
|
-
:Manager => :managers,
|
143
|
-
:Executive => :executives,
|
144
|
-
:CEO => :executives }
|
145
|
-
|
146
|
-
# Using integers to store the class type, with a :model_map hash
|
147
|
-
# and an sti_key of :type
|
148
|
-
Employee.plugin :hybrid_table_inheritance, :type,
|
149
|
-
:model_map=>{1=>:Staff, 2=>:Cook, 3=>:Manager, 4=>:Executive, 5=>:CEO}
|
150
|
-
|
151
|
-
# Using non-class name strings
|
152
|
-
Employee.plugin :hybrid_table_inheritance, :key=>:type,
|
153
|
-
:model_map=>{'staff'=>:Staff, 'cook staff'=>:Cook, 'supervisor'=>:Manager}
|
154
|
-
|
155
|
-
# By default the plugin sets the respective column value
|
156
|
-
# when a new instance is created.
|
157
|
-
Cook.create.type == 'cook staff'
|
158
|
-
Manager.create.type == 'supervisor'
|
159
|
-
|
160
|
-
# You can customize this behavior with the :key_chooser option.
|
161
|
-
# This is most useful when using a non-bijective mapping.
|
162
|
-
Employee.plugin :hybrid_table_inheritance, :key=>:type,
|
163
|
-
:model_map=>{'cook staff'=>:Cook, 'supervisor'=>:Manager},
|
164
|
-
:key_chooser=>proc{|instance| instance.model.sti_key_map[instance.model.to_s].first || 'stranger' }
|
165
|
-
|
166
|
-
# Using custom procs, with :model_map taking column values
|
167
|
-
# and yielding either a class, string, symbol, or nil,
|
168
|
-
# and :key_map taking a class object and returning the column
|
169
|
-
# value to use
|
170
|
-
Employee.plugin :single_table_inheritance, :key=>:type,
|
171
|
-
:model_map=>proc{|v| v.reverse},
|
172
|
-
:key_map=>proc{|klass| klass.name.reverse}
|
173
|
-
|
174
|
-
# You can use the same class for multiple values.
|
175
|
-
# This is mainly useful when the sti_key column contains multiple values
|
176
|
-
# which are different but do not require different code.
|
177
|
-
Employee.plugin :single_table_inheritance, :key=>:type,
|
178
|
-
:model_map=>{'staff' => "Staff",
|
179
|
-
'manager' => "Manager",
|
180
|
-
'overpayed staff' => "Staff",
|
181
|
-
'underpayed staff' => "Staff"}
|
182
|
-
|
183
|
-
One minor issue to note is that if you specify the <tt>:key_map</tt>
|
184
|
-
option as a hash, instead of having it inferred from the <tt>:model_map</tt>,
|
185
|
-
you should only use class name strings as keys, you should not use symbols
|
186
|
-
as keys.
|
187
|
-
|
188
|
-
== Options
|
189
|
-
:key :: column symbol that holds the key that identifies the class to use.
|
190
|
-
Necessary if you want to call model methods on a superclass
|
191
|
-
that return subclass instances
|
192
|
-
:model_map :: Hash or proc mapping the key column values to model class names.
|
193
|
-
:key_map :: Hash or proc mapping model class names to key column values.
|
194
|
-
Each value or return is an array of possible key column values.
|
195
|
-
:key_chooser :: proc returning key for the provided model instance
|
196
|
-
:table_map :: Hash with class name symbols keys mapping to table name symbol values
|
197
|
-
Overrides implicit table names
|
198
|
-
:subclass_load :: subclass loading strategy, defaults to :lazy
|
199
|
-
options: :eager, :eager_only, :lazy or :lazy_only
|
29
|
+
Full documentation available at http://www.rubydoc.info/gems/sequel-table_inheritance/Sequel/Plugins/HybridTableInheritance
|
@@ -9,7 +9,7 @@ module Sequel
|
|
9
9
|
# into one plugin. This plugin uses the single_table_inheritance plugin
|
10
10
|
# and should work as a drop in replacement for the class_table_inheritance plugins.
|
11
11
|
# This allows introducing new tables only when needed typically for additional
|
12
|
-
# fields or possibly referential integrity to subclassed
|
12
|
+
# fields or possibly referential integrity to subclassed rows.
|
13
13
|
#
|
14
14
|
# = Detail
|
15
15
|
#
|
@@ -18,7 +18,7 @@ module Sequel
|
|
18
18
|
# Employee
|
19
19
|
# / \
|
20
20
|
# Staff Manager
|
21
|
-
# |
|
21
|
+
# | |
|
22
22
|
# Cook Executive
|
23
23
|
# |
|
24
24
|
# CEO
|
@@ -31,16 +31,16 @@ module Sequel
|
|
31
31
|
# executives :: id, num_managers
|
32
32
|
#
|
33
33
|
# The hybrid_table_inheritance plugin assumes that the root table
|
34
|
-
# (e.g. employees) has a primary key
|
34
|
+
# (e.g. employees) has a primary key column (usually autoincrementing),
|
35
35
|
# and all other tables have a foreign key of the same name that points
|
36
|
-
# to the same
|
36
|
+
# to the same column in their superclass's table. In this example,
|
37
37
|
# the employees id column is a primary key and the id column in every
|
38
38
|
# other table is a foreign key referencing the employees id.
|
39
39
|
#
|
40
|
-
# In this example the
|
40
|
+
# In this example the staff table stores Cook model objects and the
|
41
41
|
# executives table stores CEO model objects.
|
42
42
|
#
|
43
|
-
# When using the class_table_inheritance plugin, subclasses use joined
|
43
|
+
# When using the class_table_inheritance plugin, subclasses can use joined
|
44
44
|
# datasets:
|
45
45
|
#
|
46
46
|
# Employee.dataset.sql
|
@@ -68,18 +68,18 @@ module Sequel
|
|
68
68
|
# = Subclass loading
|
69
69
|
#
|
70
70
|
# When model objects are retrieved for a superclass the result could be
|
71
|
-
# subclass objects needing additional
|
72
|
-
# This plugin can load those additional
|
73
|
-
# loading or when requested on the object with lazy loading.
|
71
|
+
# subclass objects needing additional values from other tables.
|
72
|
+
# This plugin can load those additional values immediately with eager
|
73
|
+
# loading or when requested on the model object with lazy loading.
|
74
74
|
#
|
75
75
|
# With eager loading, the additional needed rows will be loaded with the
|
76
76
|
# all or first methods. Note that eager loading does not work
|
77
|
-
# with the each method because all of the
|
78
|
-
# determine the keys for each subclass query. In that case lazy loading can
|
77
|
+
# with the each method because all of the model objects must be loaded to
|
78
|
+
# determine the keys for each subclass table query. In that case lazy loading can
|
79
79
|
# be used or the each method used on the result of the all method.
|
80
80
|
#
|
81
|
-
#
|
82
|
-
# return subclass specific
|
81
|
+
# Unless lazy loading is disabled, the lazy_attributes plugin will be
|
82
|
+
# included to return subclass specific values that were not loaded
|
83
83
|
# when calling superclass methods (since those wouldn't join
|
84
84
|
# to the subclass tables). For example:
|
85
85
|
#
|
@@ -168,26 +168,26 @@ module Sequel
|
|
168
168
|
# you should only use class name strings as keys, you should not use symbols
|
169
169
|
# as keys.
|
170
170
|
module HybridTableInheritance
|
171
|
-
# The
|
172
|
-
# to handle lazily-loaded attributes
|
173
|
-
# by superclass methods.
|
171
|
+
# The hybrid_table_inheritance plugin requires the single_table_inheritance
|
172
|
+
# plugin and the lazy_attributes plugin to handle lazily-loaded attributes
|
173
|
+
# for subclass instances returned by superclass methods.
|
174
174
|
def self.apply(model, opts = OPTS)
|
175
175
|
model.plugin :single_table_inheritance, nil
|
176
176
|
model.plugin :lazy_attributes unless opts[:subclass_load] == :eager_only
|
177
177
|
end
|
178
178
|
|
179
|
-
#
|
180
|
-
#
|
181
|
-
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
#
|
185
|
-
#
|
186
|
-
#
|
187
|
-
#
|
188
|
-
#
|
189
|
-
#
|
190
|
-
#
|
179
|
+
# Initialize the plugin using the following options:
|
180
|
+
# :key :: Column symbol that holds the key that identifies the class to use.
|
181
|
+
# Necessary if you want to call model methods on a superclass
|
182
|
+
# that return subclass instances
|
183
|
+
# :model_map :: Hash or proc mapping the key column values to model class names.
|
184
|
+
# :key_map :: Hash or proc mapping model class names to key column values.
|
185
|
+
# Each value or return is an array of possible key column values.
|
186
|
+
# :key_chooser :: proc returning key for the provided model instance
|
187
|
+
# :table_map :: Hash with class name symbols keys mapping to table name symbol values
|
188
|
+
# Overrides implicit table names
|
189
|
+
# :subclass_load :: subclass loading strategy, defaults to :lazy
|
190
|
+
# options: :eager, :eager_only, :lazy or :lazy_only
|
191
191
|
def self.configure(model, opts = OPTS)
|
192
192
|
SingleTableInheritance.configure model, opts[:key], opts
|
193
193
|
|
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "sequel-table_inheritance"
|
8
|
-
s.version = '0.1.
|
8
|
+
s.version = '0.1.2'
|
9
9
|
s.authors = ["Quinn Harris"]
|
10
10
|
s.email = ["sequel@quinnharris.me"]
|
11
11
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel-table_inheritance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Quinn Harris
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|