class-table-inheritance 1.0.0 → 1.1.0
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.
- data/README +21 -2
- data/lib/class-table-inheritance.rb +53 -22
- metadata +4 -4
data/README
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
ClassTableInheritance
|
2
|
-
|
1
|
+
ClassTableInheritance 1.1.0 BETA
|
2
|
+
================================
|
3
3
|
|
4
4
|
This is an ActiveRecord plugin designed to allow
|
5
5
|
simple multiple table (class) inheritance.
|
@@ -8,6 +8,11 @@ ClassTableInheritance
|
|
8
8
|
inherits_from plugin => http://github.com/rwl4/inherits_from and
|
9
9
|
Multiple Table Inheritance with ActiveRecord => http://mediumexposure.com/multiple-table-inheritance-active-record/
|
10
10
|
|
11
|
+
How to install
|
12
|
+
=============
|
13
|
+
|
14
|
+
gem install class-table-inheritance
|
15
|
+
|
11
16
|
Example
|
12
17
|
=======
|
13
18
|
|
@@ -15,6 +20,7 @@ Example
|
|
15
20
|
|
16
21
|
create_table :product do |t|
|
17
22
|
t.string :description, :null => false
|
23
|
+
t.string :subtype # Only if you need access of both side see example
|
18
24
|
t.decimal :price
|
19
25
|
t.timestamps
|
20
26
|
end
|
@@ -31,6 +37,7 @@ Example
|
|
31
37
|
# Models
|
32
38
|
|
33
39
|
class Product < ActiveRecord::Base
|
40
|
+
acts_as_superclass # only if you want top-down access.
|
34
41
|
end
|
35
42
|
|
36
43
|
class Book < ActiveRecord::Base
|
@@ -57,6 +64,18 @@ Example
|
|
57
64
|
book.author = "Shakespeare, William"
|
58
65
|
book.price => 14.00
|
59
66
|
book.save
|
67
|
+
|
68
|
+
Top-down access (Polymorphic)
|
69
|
+
=============================
|
70
|
+
|
71
|
+
if you want to access product and get field in the subclass do you need to create a field subtype:string in superclass and ad acts_as_superclass in superclass and now you can do like this.
|
72
|
+
|
73
|
+
product = Product.find 1 # This is a Book instance.
|
74
|
+
product.author
|
75
|
+
|
76
|
+
product = Product.find 2 # This is a Video instance.
|
77
|
+
product.genre
|
78
|
+
|
60
79
|
|
61
80
|
if you need help contanct me: bfscordeiro (at) gmail.com .
|
62
81
|
|
@@ -5,9 +5,38 @@ require 'inherits-migration'
|
|
5
5
|
# simple multiple table (class) inheritance.
|
6
6
|
class ActiveRecord::Base
|
7
7
|
attr_reader :reflection
|
8
|
-
|
9
|
-
def self.inherits_from(association_id)
|
10
8
|
|
9
|
+
def self.acts_as_superclass
|
10
|
+
if self.column_names.include?("subtype")
|
11
|
+
def self.find(*args)
|
12
|
+
super_classes = super
|
13
|
+
begin
|
14
|
+
if super_classes.kind_of? Array
|
15
|
+
super_classes.map do |item|
|
16
|
+
if !item.subtype.nil? && !item.subtype.blank?
|
17
|
+
inherits_type = Object.const_get(item.subtype.to_s)
|
18
|
+
inherits_type.send(:find, *args)
|
19
|
+
else
|
20
|
+
super_classes
|
21
|
+
end
|
22
|
+
end
|
23
|
+
else
|
24
|
+
if !super_classes.subtype.nil? && !super_classes.subtype.blank?
|
25
|
+
inherits_type = Object.const_get(super_classes.subtype.to_s)
|
26
|
+
inherits_type.send(:find, *args)
|
27
|
+
else
|
28
|
+
super_classes
|
29
|
+
end
|
30
|
+
end
|
31
|
+
rescue
|
32
|
+
super_classes
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.inherits_from(association_id)
|
39
|
+
|
11
40
|
# add an association, and set the foreign key.
|
12
41
|
has_one association_id, :foreign_key => :id
|
13
42
|
|
@@ -22,20 +51,19 @@ class ActiveRecord::Base
|
|
22
51
|
send("#{association_id}_without_autobuild") || send("build_#{association_id}")
|
23
52
|
end
|
24
53
|
|
25
|
-
|
54
|
+
|
26
55
|
# Set a method chain whith autobuild.
|
27
56
|
alias_method_chain association_id, :autobuild
|
28
57
|
|
29
|
-
|
58
|
+
|
30
59
|
# bind the before save, this method call the save of association, and
|
31
60
|
# get our generated ID an set to association_id field.
|
32
61
|
before_save :save_inherit
|
33
|
-
|
34
|
-
|
62
|
+
|
63
|
+
|
35
64
|
# Bind the validation of association.
|
36
65
|
validate :inherit_association_must_be_valid
|
37
66
|
|
38
|
-
|
39
67
|
# Generate a method to validate the field of association.
|
40
68
|
define_method("inherit_association_must_be_valid") do
|
41
69
|
association = send(association_id)
|
@@ -45,12 +73,12 @@ class ActiveRecord::Base
|
|
45
73
|
errors.add(attr, message)
|
46
74
|
end
|
47
75
|
end
|
48
|
-
|
76
|
+
|
49
77
|
valid
|
50
78
|
end
|
51
|
-
|
52
|
-
|
53
|
-
|
79
|
+
|
80
|
+
|
81
|
+
|
54
82
|
# get the class of association by reflection, this is needed because
|
55
83
|
# i need to get the methods and attributes to make a proxy methods.
|
56
84
|
reflection = create_reflection(:has_one, association_id, {}, self)
|
@@ -59,21 +87,21 @@ class ActiveRecord::Base
|
|
59
87
|
inherited_columns = association_class.column_names
|
60
88
|
# Make a filter in association colluns to exclude the colluns that
|
61
89
|
# the generalized class already have.
|
62
|
-
inherited_columns = inherited_columns.reject { |c| self.column_names.grep(c).length > 0 || c == "type" }
|
90
|
+
inherited_columns = inherited_columns.reject { |c| self.column_names.grep(c).length > 0 || c == "type" || c == "subtype"}
|
63
91
|
# Get the methods of the association class and tun it to an Array of Strings.
|
64
92
|
inherited_methods = association_class.reflections.map { |key,value| key.to_s }
|
65
93
|
# Make a filter in association methods to exclude the methods that
|
66
94
|
# the generalizae class already have.
|
67
95
|
inherited_methods = inherited_methods.reject { |c| self.reflections.map {|key, value| key.to_s }.include?(c) }
|
68
|
-
|
69
|
-
|
96
|
+
|
97
|
+
|
70
98
|
# create the proxy methods to get and set the properties and methods
|
71
99
|
# in association class.
|
72
100
|
(inherited_columns + inherited_methods).each do |name|
|
73
101
|
define_method name do
|
74
|
-
|
75
|
-
|
76
|
-
|
102
|
+
# if the field is ID than i only bind that with the association field.
|
103
|
+
# this is needed to bypass the overflow problem when the ActiveRecord
|
104
|
+
# try to get the id to find the association.
|
77
105
|
if name == 'id'
|
78
106
|
self["#{association_id}_id"]
|
79
107
|
else
|
@@ -81,12 +109,12 @@ class ActiveRecord::Base
|
|
81
109
|
assoc.send(name)
|
82
110
|
end
|
83
111
|
end
|
84
|
-
|
85
|
-
|
112
|
+
|
113
|
+
|
86
114
|
define_method "#{name}=" do |new_value|
|
87
|
-
|
88
|
-
|
89
|
-
|
115
|
+
# if the field is ID than i only bind that with the association field.
|
116
|
+
# this is needed to bypass the overflow problem when the ActiveRecord
|
117
|
+
# try to get the id to find the association.
|
90
118
|
if name == 'id'
|
91
119
|
self["#{association_id}_id"] = new_value
|
92
120
|
else
|
@@ -102,6 +130,9 @@ class ActiveRecord::Base
|
|
102
130
|
# generalized class.
|
103
131
|
define_method("save_inherit") do |*args|
|
104
132
|
association = send(association_id)
|
133
|
+
if association.attribute_names.include?("subtype")
|
134
|
+
association.subtype = self.class.to_s
|
135
|
+
end
|
105
136
|
association.save
|
106
137
|
self["#{association_id}_id"] = association.id
|
107
138
|
true
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: class-table-inheritance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Bruno Frank Cordeiro
|
@@ -15,7 +15,7 @@ autorequire: name
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-30 00:00:00 -02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|