class-table-inheritance 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|