acts_as_relation 0.0.4 → 0.0.5

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