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.
Files changed (3) hide show
  1. data/README +21 -2
  2. data/lib/class-table-inheritance.rb +53 -22
  3. 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
- # if the field is ID than i only bind that with the association field.
75
- # this is needed to bypass the overflow problem when the ActiveRecord
76
- # try to get the id to find the association.
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
- # if the field is ID than i only bind that with the association field.
88
- # this is needed to bypass the overflow problem when the ActiveRecord
89
- # try to get the id to find the association.
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: 23
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
+ - 1
8
9
  - 0
9
- - 0
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-29 00:00:00 -02:00
18
+ date: 2010-11-30 00:00:00 -02:00
19
19
  default_executable:
20
20
  dependencies: []
21
21