acts_as_relation 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -19,43 +19,62 @@ parents (via an automatically-created `has_one` associations).
19
19
  Example
20
20
  -------
21
21
 
22
- Required columns on parent model name `parent1` are
23
-
24
- 1. `parent1_type`
25
- 2. `parent1_id`
26
-
27
22
  generate models
28
23
 
29
- $ rails g model product name:string price:float product_type:string product_id:integer
24
+ $ rails g model product name:string price:float
30
25
  $ rails g model pen color:string
31
26
 
27
+ Add next option to Product Migration:
28
+
29
+ create_table :products, :as_relation_superclass => true
30
+
32
31
  add some validations and instance methods
33
32
 
34
33
  class Product < ActiveRecord::Base
35
34
  validates_presence_of :name, :price
36
-
35
+
37
36
  def hello
38
37
  puts "Hello, My name is '#{name}', my price is $#{price}."
39
38
  end
40
39
  end
41
40
 
41
+ product is superclass for all kind of products:
42
+
43
+ class Product < ActiveRecord::Base
44
+ acts_as_superclass
45
+ end
46
+
42
47
  pen inherits from product
43
48
 
44
49
  class Pen < ActiveRecord::Base
45
50
  acts_as :product
46
51
  end
47
52
 
48
- pen inhetits products validations and colomns
53
+ to get some specific class(as example: specific product - Pen) from superclass can be used method specific_class:
54
+
55
+ Pen.create :name => 'Pen A', :color=> 'black', :price => 0.42
56
+ product = Product.first
57
+ product.specific_class # will be instance of Pen class
58
+
59
+ to get name of association used between superclass and children can be used method acts_as_association_name:
60
+
61
+ Product.acts_as_association_name # 'Productable'
62
+
63
+ after deleting specific object will be removed linked superobject:
64
+
65
+ Pen.first.destroy # delete as Pen row as linked Product row
66
+
67
+ pen inherits products validations and columns
49
68
 
50
69
  p = Pen.new
51
70
  p.valid? => false
52
71
  p.errors => {:name=>["can't be blank"], :price=>["can't be blank"]}
53
-
54
- pen inherits proudct methods
72
+
73
+ pen inherits product methods
55
74
 
56
75
  pen = Pen.new(:name=>"Red Pen", :color=>:red, :price=>0.99)
57
76
  pen.hello => Hello, My name is 'Red Pen', my price is $0.99.
58
-
77
+
59
78
  we can make queries on both models
60
79
 
61
80
  Product.where("price <= 1")
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
3
 
4
+ task :default => :test
5
+
4
6
  desc 'Test the acts_as_relation plugin.'
5
7
  Rake::TestTask.new(:test) do |t|
6
8
  t.libs << 'lib'
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
 
25
25
  # Dependencies (installed via 'bundle install')...
26
26
  s.add_development_dependency("bundler")
27
+ s.add_development_dependency("rake")
27
28
  s.add_development_dependency("sqlite3")
28
29
  s.add_development_dependency("activerecord")
29
30
  end
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  def self.included(base)
5
5
  base.extend(ClassMethods)
6
6
  end
7
-
7
+
8
8
  module AccessMethods
9
9
  def define_acts_as_accessors(attribs, model_name)
10
10
  attribs.each do |attrib|
@@ -24,43 +24,62 @@ module ActiveRecord
24
24
  end
25
25
  end
26
26
  end
27
-
27
+
28
28
  module ClassMethods
29
-
29
+ def acts_as_association_name model_name = nil
30
+ suffix = 'able'
31
+ model_name = self.name unless model_name
32
+
33
+ name = model_name.to_s.demodulize.singularize
34
+ if name[-1].chr =~ /[^aeiou]/ || name[-2..-1] =~ /ge|ce/
35
+ name = name + suffix
36
+ elsif name[-7..-1] == 'ability'
37
+ name = name[0..-8] + suffix
38
+ else
39
+ name = name[0..-2] + suffix
40
+ end
41
+
42
+ name.underscore
43
+ end
44
+
30
45
  def acts_as(model_name)
31
46
  name = model_name.to_s.underscore.singularize
32
-
47
+ association_name = acts_as_association_name name
48
+
33
49
  # Create A AsModel module
34
50
  as_model = Module.new
35
51
  Object.const_set("As#{name.camelcase}", as_model)
36
-
52
+
37
53
  as_model.module_eval <<-EndModule
38
54
  def self.included(base)
39
- base.has_one :#{name}, :as => :#{name}, :autosave => true, :validate => false
55
+ base.has_one :#{name}, :as => :#{association_name}, :autosave => true, :validate => false, :dependent => :destroy
40
56
  base.validate :#{name}_must_be_valid
41
57
  base.alias_method_chain :#{name}, :autobuild
42
58
 
43
59
  base.extend ActiveRecord::Acts::AsRelation::AccessMethods
44
60
  all_attributes = #{name.camelcase.constantize}.content_columns.map(&:name)
45
- ignored_attributes = ["created_at", "updated_at", "#{name}_type"]
61
+ ignored_attributes = ["created_at", "updated_at", "#{association_name}_type"]
46
62
  associations = #{name.camelcase.constantize}.reflect_on_all_associations(:belongs_to).map! { |assoc| assoc.name }
47
63
  attributes_to_delegate = all_attributes - ignored_attributes + associations
48
64
  base.define_acts_as_accessors(attributes_to_delegate, "#{name}")
49
65
  end
50
-
66
+
51
67
  def #{name}_with_autobuild
52
68
  #{name}_without_autobuild || build_#{name}
53
69
  end
54
70
 
55
- def method_missing(method, *arg, &block)
71
+ def method_missing method, *arg, &block
72
+ #{name}.send method, *arg, &block
73
+ rescue NoMethodError
74
+ super
56
75
  end
57
-
76
+
58
77
  def respond_to?(method, include_private_methods = false)
59
78
  super || self.#{name}.respond_to?(method, include_private_methods)
60
79
  end
61
-
80
+
62
81
  protected
63
-
82
+
64
83
  def #{name}_must_be_valid
65
84
  unless #{name}.valid?
66
85
  #{name}.errors.each do |att, message|
@@ -69,13 +88,27 @@ module ActiveRecord
69
88
  end
70
89
  end
71
90
  EndModule
72
-
91
+
73
92
  class_eval do
74
93
  include "As#{name.camelcase}".constantize
75
94
  end
76
95
  end
77
-
96
+
97
+ def acts_as_superclass
98
+ association_name = acts_as_association_name
99
+
100
+ class_eval <<-CLASS
101
+ belongs_to :#{association_name}, :polymorphic => true
102
+
103
+ def specific_class
104
+ self.#{association_name}
105
+ end
106
+ CLASS
107
+ end
108
+
78
109
  end
79
110
  end
80
111
  end
81
112
  end
113
+
114
+ ActiveRecord::Base.send :include, ActiveRecord::Acts::AsRelation
@@ -0,0 +1,27 @@
1
+ module ActiveRecord
2
+ module Acts
3
+ module AsRelationSuperclassMigration
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ alias_method_chain :create_table, :as_relation_superclass
8
+ end
9
+ end
10
+
11
+ def create_table_with_as_relation_superclass(table_name, options = {})
12
+ association_name = ActiveRecord::Base.acts_as_association_name table_name
13
+
14
+ create_table_without_as_relation_superclass(table_name, options) do |td|
15
+ if options[:as_relation_superclass]
16
+ td.integer "#{association_name}_id"
17
+ td.string "#{association_name}_type"
18
+ end
19
+
20
+ yield td if block_given?
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ ActiveRecord::ConnectionAdapters::SchemaStatements.send :include, ActiveRecord::Acts::AsRelationSuperclassMigration
@@ -1,2 +1,2 @@
1
1
  require 'active_record/acts/as_relation'
2
- ActiveRecord::Base.send :include, ActiveRecord::Acts::AsRelation
2
+ require 'active_record/acts/as_relation_superclass_migration'
data/lib/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module ActiveRecord
2
2
  module Acts
3
3
  module AsRelation
4
- VERSION = "0.0.4"
4
+ VERSION = "0.0.5"
5
5
  end
6
6
  end
7
7
  end
@@ -74,6 +74,45 @@ class ActsAsRelationTest < ActiveSupport::TestCase
74
74
  assert_equal store, pen.store
75
75
  end
76
76
 
77
+ test "call parent methods" do
78
+ pen = Pen.new(:name=>"RedPen", :price=>0.59, :color=>"red")
79
+ assert_equal pen.parent_method, "RedPen - 0.59"
80
+ end
81
+
82
+ test "call unexisted method" do
83
+ assert_raise NoMethodError do
84
+ pen = Pen.new
85
+ pen.unexisted_method
86
+ end
87
+
88
+ end
89
+
90
+ test "acts as association name" do
91
+ assert_equal Pencil.acts_as_association_name, 'pencilable'
92
+ assert_equal Pencil.acts_as_association_name( Pen ), 'penable'
93
+ end
94
+
95
+ test "acts as superclass" do
96
+ pen = Pen.create(:name => "RedPen", :price => 0.59, :color => "red")
97
+ product = pen.product
98
+
99
+ assert_equal product.specific_class.class, Pen
100
+ end
101
+
102
+ test "destroy action" do
103
+ pen = Pen.create(:name => "RedPen", :price => 0.59, :color => "red")
104
+ product = pen.product
105
+
106
+ pen.destroy
107
+
108
+ assert_raise ActiveRecord::RecordNotFound do
109
+ Product.find product.id
110
+ end
111
+ assert_raise ActiveRecord::RecordNotFound do
112
+ Pen.find pen.id
113
+ end
114
+ end
115
+
77
116
  end
78
117
 
79
118
  #ActiveRecord::Base.connection.tables.each do |table|
data/test/schema.rb CHANGED
@@ -13,17 +13,13 @@ ActiveRecord::Schema.define(:version => 1) do
13
13
  t.string :store_name
14
14
  end
15
15
 
16
- create_table :products do |t|
16
+ create_table :products, :as_relation_superclass => true do |t|
17
17
  t.string :name
18
18
  t.float :price
19
- t.string :product_type
20
- t.integer :product_id
21
19
  end
22
20
 
23
- create_table :pens do |t|
21
+ create_table :pens, :as_relation_superclass => true do |t|
24
22
  t.string :color
25
- t.integer :pen_id
26
- t.string :pen_type
27
23
  end
28
24
 
29
25
  create_table :pencils
@@ -34,11 +30,19 @@ class Store < ActiveRecord::Base
34
30
  end
35
31
 
36
32
  class Product < ActiveRecord::Base
33
+ acts_as_superclass
34
+
37
35
  belongs_to :store
38
36
  validates_presence_of :name, :price
37
+
38
+ def parent_method
39
+ "#{name} - #{price}"
40
+ end
39
41
  end
40
42
 
41
43
  class Pen < ActiveRecord::Base
44
+ acts_as_superclass
45
+
42
46
  acts_as :product
43
47
  validates_presence_of :color
44
48
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_relation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-12 00:00:00.000000000Z
12
+ date: 2011-12-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
- requirement: &14204820 !ruby/object:Gem::Requirement
16
+ requirement: &10491360 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,21 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *14204820
24
+ version_requirements: *10491360
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &10490800 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *10490800
25
36
  - !ruby/object:Gem::Dependency
26
37
  name: sqlite3
27
- requirement: &14203940 !ruby/object:Gem::Requirement
38
+ requirement: &10490200 !ruby/object:Gem::Requirement
28
39
  none: false
29
40
  requirements:
30
41
  - - ! '>='
@@ -32,10 +43,10 @@ dependencies:
32
43
  version: '0'
33
44
  type: :development
34
45
  prerelease: false
35
- version_requirements: *14203940
46
+ version_requirements: *10490200
36
47
  - !ruby/object:Gem::Dependency
37
48
  name: activerecord
38
- requirement: &14178400 !ruby/object:Gem::Requirement
49
+ requirement: &10489620 !ruby/object:Gem::Requirement
39
50
  none: false
40
51
  requirements:
41
52
  - - ! '>='
@@ -43,7 +54,7 @@ dependencies:
43
54
  version: '0'
44
55
  type: :development
45
56
  prerelease: false
46
- version_requirements: *14178400
57
+ version_requirements: *10489620
47
58
  description: This 'acts_as' extension provides multi-table inheritance for rails models.
48
59
  email: hsn.zamani@gmail.com
49
60
  executables: []
@@ -57,6 +68,7 @@ files:
57
68
  - acts_as_relation.gemspec
58
69
  - init.rb
59
70
  - lib/active_record/acts/as_relation.rb
71
+ - lib/active_record/acts/as_relation_superclass_migration.rb
60
72
  - lib/acts_as_relation.rb
61
73
  - lib/version.rb
62
74
  - test/acts_as_relation_test.rb
@@ -86,4 +98,7 @@ rubygems_version: 1.8.10
86
98
  signing_key:
87
99
  specification_version: 3
88
100
  summary: Easy multi-table inheritance for rails
89
- test_files: []
101
+ test_files:
102
+ - test/acts_as_relation_test.rb
103
+ - test/schema.rb
104
+ - test/test_helper.rb