acts_as_relation 1.0.0 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +91 -62
  6. data/README.rdoc +28 -5
  7. data/Rakefile +1 -1
  8. data/acts_as_relation.gemspec +10 -10
  9. data/lib/active_record/acts_as_relation.rb +45 -126
  10. data/lib/active_record/acts_as_relation/access_methods.rb +63 -0
  11. data/lib/active_record/acts_as_relation/acts_as.rb +34 -0
  12. data/lib/active_record/acts_as_relation/acts_as_modules.rb +109 -0
  13. data/lib/active_record/acts_as_relation/superclass_migration.rb +32 -0
  14. data/lib/acts_as_relation.rb +4 -1
  15. data/lib/version.rb +1 -1
  16. data/spec/acts_as_relation_spec.rb +136 -59
  17. data/spec/acts_as_superclass_spec.rb +7 -7
  18. data/spec/dummy/app/models/product.rb +4 -0
  19. data/spec/dummy/app/models/store.rb +1 -0
  20. data/spec/dummy/config/application.rb +2 -49
  21. data/spec/dummy/config/boot.rb +1 -1
  22. data/spec/dummy/config/environments/development.rb +0 -3
  23. data/spec/dummy/config/environments/test.rb +1 -6
  24. data/spec/dummy/db/schema.rb +4 -0
  25. data/spec/spec_helper.rb +10 -7
  26. metadata +33 -73
  27. data/lib/active_record/acts_as_relation_superclass_migration.rb +0 -30
  28. data/spec/dummy/.rspec +0 -1
  29. data/spec/dummy/README.rdoc +0 -261
  30. data/spec/dummy/app/assets/javascripts/application.js +0 -15
  31. data/spec/dummy/app/assets/stylesheets/application.css +0 -13
  32. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  33. data/spec/dummy/app/helpers/application_helper.rb +0 -2
  34. data/spec/dummy/app/mailers/.gitkeep +0 -0
  35. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  36. data/spec/dummy/config/environments/production.rb +0 -65
  37. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  38. data/spec/dummy/config/initializers/inflections.rb +0 -15
  39. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  40. data/spec/dummy/config/initializers/secret_token.rb +0 -7
  41. data/spec/dummy/config/initializers/session_store.rb +0 -8
  42. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  43. data/spec/dummy/config/locales/en.yml +0 -5
  44. data/spec/dummy/config/routes.rb +0 -58
  45. data/spec/dummy/lib/assets/.gitkeep +0 -0
  46. data/spec/dummy/public/404.html +0 -26
  47. data/spec/dummy/public/422.html +0 -26
  48. data/spec/dummy/public/500.html +0 -25
  49. data/spec/dummy/public/favicon.ico +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a72ef528265e4e2439caa3e118c83ba0b8a0e236
4
- data.tar.gz: 9c1d9259eb36d2fe48dcd572ced40e1451e53ce0
3
+ metadata.gz: bc6b69987a960f143e2cf8b1b7fda99dd40bc1e4
4
+ data.tar.gz: 09eaed2afe535c9cf739db050575a0923cd1e80b
5
5
  SHA512:
6
- metadata.gz: b8e696a7fbeac93377ef709302730f00740274b7db2d13523e4f1735e1ca75f2f2507a623525a23d23dad0a11ac5bf296e1e5fee8986d4aa0255d71ced472aaa
7
- data.tar.gz: a181edf19a4b1f5fd9e73502323d691bfa5694fc6d1dddd2ca92445a55ae801a6169e9ce8e664d38c4e7364fcdd4021d5c922c9d22490db881756604642ce802
6
+ metadata.gz: d7ddfd42cd6f28d0d5a78819b92b7cbf9f64f72705a5f6b90d1ed541169304508d0990fb613840104b352e130622d44f68392e5a769291c045e3fa1ecb9839a6
7
+ data.tar.gz: f61af829ee9f54158e59ed5e3aa6e7b9da82c3ef3c44ae7999c383c4fcbfbd5e45b66f1efe645ba3996f7c94e5138b0cd3d76387be36d6688858b7de792e7def
data/.gitignore CHANGED
@@ -7,3 +7,4 @@ doc/*
7
7
  *.sqlite3
8
8
  *.log
9
9
  spec/dummy/tmp/*
10
+ coverage/*
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.1
4
+ - 2.0.0
5
+ - 1.9.3
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in gemspec
4
4
  gemspec
5
+
6
+ gem 'coveralls', require: false
data/Gemfile.lock CHANGED
@@ -1,97 +1,125 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- acts_as_relation (1.0.0)
5
- activerecord
4
+ acts_as_relation (1.1.0)
5
+ activerecord (>= 3)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- actionmailer (4.0.0)
11
- actionpack (= 4.0.0)
12
- mail (~> 2.5.3)
13
- actionpack (4.0.0)
14
- activesupport (= 4.0.0)
15
- builder (~> 3.1.0)
16
- erubis (~> 2.7.0)
10
+ actionmailer (4.1.4)
11
+ actionpack (= 4.1.4)
12
+ actionview (= 4.1.4)
13
+ mail (~> 2.5.4)
14
+ actionpack (4.1.4)
15
+ actionview (= 4.1.4)
16
+ activesupport (= 4.1.4)
17
17
  rack (~> 1.5.2)
18
18
  rack-test (~> 0.6.2)
19
- activemodel (4.0.0)
20
- activesupport (= 4.0.0)
21
- builder (~> 3.1.0)
22
- activerecord (4.0.0)
23
- activemodel (= 4.0.0)
24
- activerecord-deprecated_finders (~> 1.0.2)
25
- activesupport (= 4.0.0)
26
- arel (~> 4.0.0)
27
- activerecord-deprecated_finders (1.0.3)
28
- activesupport (4.0.0)
29
- i18n (~> 0.6, >= 0.6.4)
30
- minitest (~> 4.2)
31
- multi_json (~> 1.3)
19
+ actionview (4.1.4)
20
+ activesupport (= 4.1.4)
21
+ builder (~> 3.1)
22
+ erubis (~> 2.7.0)
23
+ activemodel (4.1.4)
24
+ activesupport (= 4.1.4)
25
+ builder (~> 3.1)
26
+ activerecord (4.1.4)
27
+ activemodel (= 4.1.4)
28
+ activesupport (= 4.1.4)
29
+ arel (~> 5.0.0)
30
+ activesupport (4.1.4)
31
+ i18n (~> 0.6, >= 0.6.9)
32
+ json (~> 1.7, >= 1.7.7)
33
+ minitest (~> 5.1)
32
34
  thread_safe (~> 0.1)
33
- tzinfo (~> 0.3.37)
34
- arel (4.0.0)
35
- atomic (1.1.10)
36
- builder (3.1.4)
37
- database_cleaner (1.0.1)
38
- diff-lcs (1.2.4)
35
+ tzinfo (~> 1.1)
36
+ arel (5.0.1.20140414130214)
37
+ builder (3.2.2)
38
+ coveralls (0.7.0)
39
+ multi_json (~> 1.3)
40
+ rest-client
41
+ simplecov (>= 0.7)
42
+ term-ansicolor
43
+ thor
44
+ database_cleaner (1.3.0)
45
+ diff-lcs (1.2.5)
46
+ docile (1.1.5)
39
47
  erubis (2.7.0)
40
48
  hike (1.2.3)
41
- i18n (0.6.4)
49
+ i18n (0.6.11)
50
+ json (1.8.1)
42
51
  mail (2.5.4)
43
52
  mime-types (~> 1.16)
44
53
  treetop (~> 1.4.8)
45
- mime-types (1.23)
46
- minitest (4.7.5)
47
- multi_json (1.7.7)
48
- polyglot (0.3.3)
54
+ mime-types (1.25.1)
55
+ minitest (5.4.0)
56
+ multi_json (1.10.1)
57
+ netrc (0.7.7)
58
+ polyglot (0.3.5)
49
59
  rack (1.5.2)
50
60
  rack-test (0.6.2)
51
61
  rack (>= 1.0)
52
- rails (4.0.0)
53
- actionmailer (= 4.0.0)
54
- actionpack (= 4.0.0)
55
- activerecord (= 4.0.0)
56
- activesupport (= 4.0.0)
62
+ rails (4.1.4)
63
+ actionmailer (= 4.1.4)
64
+ actionpack (= 4.1.4)
65
+ actionview (= 4.1.4)
66
+ activemodel (= 4.1.4)
67
+ activerecord (= 4.1.4)
68
+ activesupport (= 4.1.4)
57
69
  bundler (>= 1.3.0, < 2.0)
58
- railties (= 4.0.0)
59
- sprockets-rails (~> 2.0.0)
60
- railties (4.0.0)
61
- actionpack (= 4.0.0)
62
- activesupport (= 4.0.0)
70
+ railties (= 4.1.4)
71
+ sprockets-rails (~> 2.0)
72
+ railties (4.1.4)
73
+ actionpack (= 4.1.4)
74
+ activesupport (= 4.1.4)
63
75
  rake (>= 0.8.7)
64
76
  thor (>= 0.18.1, < 2.0)
65
- rake (10.1.0)
66
- rspec-core (2.13.1)
67
- rspec-expectations (2.13.0)
68
- diff-lcs (>= 1.1.3, < 2.0)
69
- rspec-mocks (2.13.1)
70
- rspec-rails (2.13.2)
77
+ rake (10.3.2)
78
+ rest-client (1.7.1)
79
+ mime-types (>= 1.16, < 3.0)
80
+ netrc (~> 0.7)
81
+ rspec-core (3.0.2)
82
+ rspec-support (~> 3.0.0)
83
+ rspec-expectations (3.0.2)
84
+ diff-lcs (>= 1.2.0, < 2.0)
85
+ rspec-support (~> 3.0.0)
86
+ rspec-mocks (3.0.2)
87
+ rspec-support (~> 3.0.0)
88
+ rspec-rails (3.0.1)
71
89
  actionpack (>= 3.0)
72
90
  activesupport (>= 3.0)
73
91
  railties (>= 3.0)
74
- rspec-core (~> 2.13.0)
75
- rspec-expectations (~> 2.13.0)
76
- rspec-mocks (~> 2.13.0)
77
- sprockets (2.10.0)
92
+ rspec-core (~> 3.0.0)
93
+ rspec-expectations (~> 3.0.0)
94
+ rspec-mocks (~> 3.0.0)
95
+ rspec-support (~> 3.0.0)
96
+ rspec-support (3.0.2)
97
+ simplecov (0.8.2)
98
+ docile (~> 1.1.0)
99
+ multi_json
100
+ simplecov-html (~> 0.8.0)
101
+ simplecov-html (0.8.0)
102
+ sprockets (2.12.1)
78
103
  hike (~> 1.2)
79
104
  multi_json (~> 1.0)
80
105
  rack (~> 1.0)
81
106
  tilt (~> 1.1, != 1.3.0)
82
- sprockets-rails (2.0.0)
107
+ sprockets-rails (2.1.3)
83
108
  actionpack (>= 3.0)
84
109
  activesupport (>= 3.0)
85
110
  sprockets (~> 2.8)
86
- sqlite3 (1.3.7)
87
- thor (0.18.1)
88
- thread_safe (0.1.0)
89
- atomic
111
+ sqlite3 (1.3.9)
112
+ term-ansicolor (1.3.0)
113
+ tins (~> 1.0)
114
+ thor (0.19.1)
115
+ thread_safe (0.3.4)
90
116
  tilt (1.4.1)
91
- treetop (1.4.14)
117
+ tins (1.3.0)
118
+ treetop (1.4.15)
92
119
  polyglot
93
120
  polyglot (>= 0.3.1)
94
- tzinfo (0.3.37)
121
+ tzinfo (1.2.1)
122
+ thread_safe (~> 0.1)
95
123
 
96
124
  PLATFORMS
97
125
  ruby
@@ -99,8 +127,9 @@ PLATFORMS
99
127
  DEPENDENCIES
100
128
  acts_as_relation!
101
129
  bundler
130
+ coveralls
102
131
  database_cleaner
103
- rails
132
+ rails (>= 3)
104
133
  rake
105
- rspec-rails
134
+ rspec-rails (>= 2.14)
106
135
  sqlite3
data/README.rdoc CHANGED
@@ -1,10 +1,14 @@
1
+ {<img src="https://travis-ci.org/hzamani/acts_as_relation.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/hzamani/acts_as_relation]
2
+ {<img src="https://coveralls.io/repos/hzamani/acts_as_relation/badge.png?branch=master" alt="Coverage Status" />}[https://coveralls.io/r/hzamani/acts_as_relation?branch=master]
3
+ {<img src="https://codeclimate.com/github/hzamani/acts_as_relation.png" />}[https://codeclimate.com/github/hzamani/acts_as_relation]
4
+
1
5
  = ActsAsRelation
2
6
  This gem helps implement multiple-table-inheritance (MTI) methods to your ActiveRecord models.
3
7
  By default, ActiveRecord only supports single-table inheritance (STI).
4
8
  MTI gives you the benefits of STI but without having to place dozens of empty fields into a single table.
5
9
 
6
- Take a traditional e-commerce application for example...
7
- A product has common attributes (+name+, +price+, +image+ ...),
10
+ Take a traditional e-commerce application for example...
11
+ A product has common attributes (+name+, +price+, +image+ ...),
8
12
  while each type of product has its own attributes...
9
13
  +pen+ has +color+, +book+ has +author+ and +publisher+ and so on.
10
14
 
@@ -18,7 +22,7 @@ If you are using Rails 3 you must use '~> 0.1' version specifier in Gemfile.
18
22
 
19
23
  == Usage
20
24
  +acts_as_relation+ uses a polymorphic +has_one+
21
- association to simulate multiple-table inheritance.
25
+ association to simulate multiple-table inheritance.
22
26
  For the e-commerce example you would declare the product as a +supermodel+ and all types of it as +acts_as+ +:product+
23
27
  (if you prefer you can use their aliases +is_a+ and +is_a_superclass+)
24
28
 
@@ -34,6 +38,10 @@ For the e-commerce example you would declare the product as a +supermodel+ and a
34
38
  acts_as :product
35
39
  end
36
40
 
41
+ class Store < ActiveRecord::Base
42
+ has_many :products
43
+ end
44
+
37
45
  To make this work, you need to declare both a foreign key column and a type column
38
46
  in the model that declares superclass. To do this you can set +:as_relation_superclass+
39
47
  option to +true+ on +products+ +create_table+ (or pass it name of the association):
@@ -43,17 +51,25 @@ option to +true+ on +products+ +create_table+ (or pass it name of the associatio
43
51
  end
44
52
 
45
53
  Or declare them as you do on a +polymorphic+ +belongs_to+ association, it this case
46
- you must pass name to +acts_as+ in +:as+ option:
54
+ you must pass name to +acts_as+ and +acts_as_superclass+ in +:as+ option:
47
55
 
48
56
  change_table :products do |t|
49
57
  t.integer :producible_id
50
58
  t.string :producible_type
51
59
  end
52
60
 
61
+ class Product < ActiveRecord::Base
62
+ acts_as_superclass :as => :producible
63
+ end
64
+
53
65
  class Pen < ActiveRecord::Base
54
66
  acts_as :product, :as => :producible
55
67
  end
56
68
 
69
+ class Book < ActiveRecord::Base
70
+ acts_as :product, :as => :producible
71
+ end
72
+
57
73
  Now +Pen+ and +Book+ *act* *as* +Product+. This means that they inherit +Product+
58
74
  _attributes_, _associations_, _validations_ and _methods_.
59
75
 
@@ -81,7 +97,13 @@ methods (includeing accessors) so you can access them directly.
81
97
 
82
98
  On the other hand you can always access a specific object from its parent by calling +specific+ method on it:
83
99
 
84
- Product.first.specific # will return a specific product, a pen for example
100
+ Product.first.specific # will return a specific product, a pen for example
101
+
102
+ In +has_many+ case you can use subclasses:
103
+
104
+ store = Store.create
105
+ store.products << Pen.create
106
+ store.products.first # => <Pen: ...>
85
107
 
86
108
  == Options
87
109
  The +acts_as+ relation support these options:
@@ -106,4 +128,5 @@ Note that support for +:conditions+ and +:include+ has been removed. In their pl
106
128
  +where()+ and +includes()+:
107
129
 
108
130
  acts_as :product, -> { where(color: "yellow") }
131
+ acts_as :person, -> { includes(:friends) }
109
132
 
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rake'
2
2
  require 'rspec/core/rake_task'
3
3
 
4
- task :default => :spec
4
+ task default: :spec
5
5
 
6
6
  desc 'Run specs'
7
7
  RSpec::Core::RakeTask.new
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
3
3
  require 'version'
4
4
 
5
5
  Gem::Specification.new do |s|
@@ -14,20 +14,20 @@ Gem::Specification.new do |s|
14
14
  s.summary = 'Easy multi-table inheritance for rails'
15
15
  s.description = "This 'acts_as' extension provides multi-table inheritance for rails models."
16
16
 
17
-
18
17
  # Load Paths...
19
18
  s.files = `git ls-files`.split("\n")
20
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
22
21
  s.require_paths = ['lib']
23
22
 
23
+ s.required_ruby_version = '>= 1.9'
24
24
 
25
25
  # Dependencies (installed via 'bundle install')...
26
- s.add_development_dependency "rake"
27
- s.add_development_dependency "bundler"
28
- s.add_development_dependency "sqlite3"
29
- s.add_development_dependency "rspec-rails"
30
- s.add_development_dependency "rails"
31
- s.add_development_dependency "database_cleaner"
32
- s.add_dependency "activerecord"
26
+ s.add_development_dependency 'rake'
27
+ s.add_development_dependency 'bundler'
28
+ s.add_development_dependency 'sqlite3'
29
+ s.add_development_dependency 'rspec-rails', '~> 2.14'
30
+ s.add_development_dependency 'rails', '~> 4.0'
31
+ s.add_development_dependency 'database_cleaner'
32
+ s.add_dependency 'activerecord', '~> 4.0'
33
33
  end
@@ -1,159 +1,78 @@
1
1
  module ActiveRecord
2
-
3
- module ActsAsModules end
4
-
5
2
  module ActsAsRelation
6
3
  extend ActiveSupport::Concern
7
4
 
8
- module AccessMethods
9
- protected
10
- def define_acts_as_accessors(attribs, model_name)
11
- attribs.each do |attrib|
12
- code = <<-EndCode
13
- def #{attrib}
14
- #{model_name}.#{attrib}
15
- end
16
-
17
- def #{attrib}=(value)
18
- #{model_name}.#{attrib} = value
19
- end
20
-
21
- def #{attrib}?
22
- #{model_name}.#{attrib}?
23
- end
24
- EndCode
25
- class_eval code, __FILE__, __LINE__
26
- end
27
- end
5
+ included do
6
+ alias_method :acts_as?, :is_a?
28
7
  end
29
8
 
30
9
  module ClassMethods
31
- def acts_as(model_name, scope=nil, options={})
32
- if scope.is_a?(Hash)
33
- options = scope
34
- scope = nil
35
- end
36
-
37
- if options[:conditions]
38
- ActiveSupport::Deprecation.warn(":conditions is no longer supported by acts_as. Please use `where()` instead. Example: `acts_as :person, -> { where(name: 'John') }`")
39
- end
40
- if options[:include]
41
- ActiveSupport::Deprecation.warn(":include is no longer supported by acts_as. Please use `includes()` instead. Example: `acts_as :person, -> { includes(:friends) }`")
42
- end
43
-
44
- name = model_name.to_s.underscore.singularize
45
- class_name = options[:class_name] || name.camelcase
46
- association_name = options[:as] || acts_as_association_name(name)
47
- module_name = "ActsAs#{name.camelcase}"
48
-
49
- unless ActiveRecord::ActsAsModules.const_defined? module_name
50
- # Create ActsAsModel module
51
- acts_as_model = Module.new
52
- ActiveRecord::ActsAsModules.const_set(module_name, acts_as_model)
53
-
54
- has_one_options = {
55
- :as => association_name,
56
- :class_name => class_name,
57
- :autosave => true,
58
- :validate => false,
59
- :dependent => options.fetch(:dependent, :destroy),
60
- }
61
-
62
- acts_as_model.module_eval do
63
- singleton = class << self ; self end
64
- singleton.send :define_method, :included do |base|
65
- base.has_one name.to_sym, scope, has_one_options
66
- base.validate "#{name}_must_be_valid".to_sym
67
- base.alias_method_chain name.to_sym, :autobuild
68
-
69
- base.extend ActiveRecord::ActsAsRelation::AccessMethods
70
- attributes = class_name.constantize.content_columns.map(&:name)
71
- associations = class_name.constantize.reflect_on_all_associations.map(&:name)
72
- ignored = ["created_at", "updated_at", "#{association_name}_id", "#{association_name}_type", "#{association_name}"]
73
- attributes_to_delegate = attributes + associations - ignored
74
- base.send :define_acts_as_accessors, attributes_to_delegate, name
75
-
76
- if defined?(::ProtectedAttributes)
77
- base.attr_accessible.update(class_name.constantize.attr_accessible)
78
- end
79
- end
80
-
81
- define_method "#{name}_with_autobuild" do
82
- send("#{name}_without_autobuild") || send("build_#{name}")
83
- end
84
-
85
- define_method :method_missing do |method, *arg, &block|
86
- begin
87
- raise NoMethodError if method.to_s == 'id' || method.to_s == name
88
-
89
- send(name).send(method, *arg, &block)
90
- rescue NoMethodError
91
- super(method, *arg, &block)
92
- end
93
- end
94
-
95
- define_method 'respond_to?' do |method, include_private_methods = false|
96
- super(method, include_private_methods) || send(name).respond_to?(method, include_private_methods)
97
- end
98
-
99
- protected
100
-
101
- define_method "#{name}_must_be_valid" do
102
- unless send(name).valid?
103
- send(name).errors.each do |att, message|
104
- errors.add(att, message)
105
- end
106
- end
107
- end
108
- end
109
- end
10
+ def acts_as(model_name, scope = nil, options = {})
11
+ acts_as = ActsAs.new(model_name, scope, options)
110
12
 
111
13
  class_eval do
112
- include "ActiveRecord::ActsAsModules::#{module_name}".constantize
113
- end
14
+ include ActiveRecord::ActsAsRelation::ActsAsModules[acts_as]
114
15
 
115
- if options.fetch :auto_join, true
116
- class_eval "default_scope -> { joins(:#{name}) }"
16
+ default_scope -> { includes(acts_as.name) }
117
17
  end
118
18
 
119
- class_eval "default_scope -> { includes(:#{name}) }"
19
+ class_eval { default_scope -> { joins(acts_as.name) } } if options.fetch :auto_join, true
120
20
 
121
- code = <<-EndCode
21
+ instance_eval <<-EndCode, __FILE__, __LINE__ + 1
122
22
  def acts_as_other_model?
123
23
  true
124
24
  end
125
25
 
126
26
  def acts_as_model_name
127
- :#{name}
27
+ "#{acts_as.name}".to_sym
128
28
  end
129
29
  EndCode
130
- instance_eval code, __FILE__, __LINE__
131
30
  end
132
- alias :is_a :acts_as
31
+ alias_method :is_a, :acts_as
32
+
33
+ def acts_as_superclass(options = {})
34
+ association_name = (options[:as] || acts_as_association_name).to_sym
133
35
 
134
- def acts_as_superclass options={}
135
- association_name = options[:as] || acts_as_association_name
36
+ class_eval do
37
+ belongs_to association_name, polymorphic: true, dependent: :delete
136
38
 
137
- code = <<-EndCode
138
- belongs_to :#{association_name}, :polymorphic => true
39
+ alias_method :specific, association_name
40
+ alias_method :specific_class, :specific
139
41
 
140
- def specific
141
- self.#{association_name}
42
+ def method_missing(method, *arg, &block)
43
+ if specific && specific.respond_to?(method)
44
+ specific.send(method, *arg, &block)
45
+ else
46
+ super
47
+ end
142
48
  end
143
- alias :specific_class :specific
144
- EndCode
145
- class_eval code, __FILE__, __LINE__
49
+
50
+ def is_a?(klass)
51
+ (specific && specific.class == klass) ? true : super
52
+ end
53
+ alias_method :instance_of?, :is_a?
54
+ alias_method :kind_of?, :is_a?
55
+ end
146
56
  end
147
- alias :is_a_superclass :acts_as_superclass
57
+ alias_method :is_a_superclass, :acts_as_superclass
148
58
 
149
- def acts_as_association_name model_name=nil
150
- model_name ||= self.name
59
+ def is_a?(klass)
60
+ if respond_to?(:acts_as_model_name) && acts_as_model_name == klass.name.downcase.to_sym
61
+ true
62
+ else
63
+ super
64
+ end
65
+ end
66
+ alias_method :acts_as?, :is_a?
67
+
68
+ def acts_as_association_name(model_name = nil)
69
+ model_name ||= name
151
70
  "as_#{model_name.to_s.demodulize.singularize.underscore}"
152
71
  end
153
72
  end
154
73
  end
155
- end
156
74
 
157
- class ActiveRecord::Base
158
- include ActiveRecord::ActsAsRelation
75
+ class Base
76
+ include ActsAsRelation
77
+ end
159
78
  end