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.
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