acts_as_relation 1.0.0 → 1.1.2
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +91 -62
- data/README.rdoc +28 -5
- data/Rakefile +1 -1
- data/acts_as_relation.gemspec +10 -10
- data/lib/active_record/acts_as_relation.rb +45 -126
- data/lib/active_record/acts_as_relation/access_methods.rb +63 -0
- data/lib/active_record/acts_as_relation/acts_as.rb +34 -0
- data/lib/active_record/acts_as_relation/acts_as_modules.rb +109 -0
- data/lib/active_record/acts_as_relation/superclass_migration.rb +32 -0
- data/lib/acts_as_relation.rb +4 -1
- data/lib/version.rb +1 -1
- data/spec/acts_as_relation_spec.rb +136 -59
- data/spec/acts_as_superclass_spec.rb +7 -7
- data/spec/dummy/app/models/product.rb +4 -0
- data/spec/dummy/app/models/store.rb +1 -0
- data/spec/dummy/config/application.rb +2 -49
- data/spec/dummy/config/boot.rb +1 -1
- data/spec/dummy/config/environments/development.rb +0 -3
- data/spec/dummy/config/environments/test.rb +1 -6
- data/spec/dummy/db/schema.rb +4 -0
- data/spec/spec_helper.rb +10 -7
- metadata +33 -73
- data/lib/active_record/acts_as_relation_superclass_migration.rb +0 -30
- data/spec/dummy/.rspec +0 -1
- data/spec/dummy/README.rdoc +0 -261
- data/spec/dummy/app/assets/javascripts/application.js +0 -15
- data/spec/dummy/app/assets/stylesheets/application.css +0 -13
- data/spec/dummy/app/controllers/application_controller.rb +0 -3
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config/environments/production.rb +0 -65
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/inflections.rb +0 -15
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -7
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -58
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -25
- data/spec/dummy/public/favicon.ico +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc6b69987a960f143e2cf8b1b7fda99dd40bc1e4
|
4
|
+
data.tar.gz: 09eaed2afe535c9cf739db050575a0923cd1e80b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7ddfd42cd6f28d0d5a78819b92b7cbf9f64f72705a5f6b90d1ed541169304508d0990fb613840104b352e130622d44f68392e5a769291c045e3fa1ecb9839a6
|
7
|
+
data.tar.gz: f61af829ee9f54158e59ed5e3aa6e7b9da82c3ef3c44ae7999c383c4fcbfbd5e45b66f1efe645ba3996f7c94e5138b0cd3d76387be36d6688858b7de792e7def
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,97 +1,125 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
acts_as_relation (1.
|
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.
|
11
|
-
actionpack (= 4.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
20
|
-
activesupport (= 4.
|
21
|
-
builder (~> 3.1
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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 (~>
|
34
|
-
arel (
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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.
|
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.
|
46
|
-
minitest (4.
|
47
|
-
multi_json (1.
|
48
|
-
|
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.
|
53
|
-
actionmailer (= 4.
|
54
|
-
actionpack (= 4.
|
55
|
-
|
56
|
-
|
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.
|
59
|
-
sprockets-rails (~> 2.0
|
60
|
-
railties (4.
|
61
|
-
actionpack (= 4.
|
62
|
-
activesupport (= 4.
|
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.
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
rspec-
|
70
|
-
|
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 (~>
|
75
|
-
rspec-expectations (~>
|
76
|
-
rspec-mocks (~>
|
77
|
-
|
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.
|
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.
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
117
|
+
tins (1.3.0)
|
118
|
+
treetop (1.4.15)
|
92
119
|
polyglot
|
93
120
|
polyglot (>= 0.3.1)
|
94
|
-
tzinfo (
|
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
|
-
|
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
data/acts_as_relation.gemspec
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
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
|
27
|
-
s.add_development_dependency
|
28
|
-
s.add_development_dependency
|
29
|
-
s.add_development_dependency
|
30
|
-
s.add_development_dependency
|
31
|
-
s.add_development_dependency
|
32
|
-
s.add_dependency
|
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
|
-
|
9
|
-
|
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
|
-
|
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
|
113
|
-
end
|
14
|
+
include ActiveRecord::ActsAsRelation::ActsAsModules[acts_as]
|
114
15
|
|
115
|
-
|
116
|
-
class_eval "default_scope -> { joins(:#{name}) }"
|
16
|
+
default_scope -> { includes(acts_as.name) }
|
117
17
|
end
|
118
18
|
|
119
|
-
class_eval
|
19
|
+
class_eval { default_scope -> { joins(acts_as.name) } } if options.fetch :auto_join, true
|
120
20
|
|
121
|
-
|
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
|
-
|
27
|
+
"#{acts_as.name}".to_sym
|
128
28
|
end
|
129
29
|
EndCode
|
130
|
-
instance_eval code, __FILE__, __LINE__
|
131
30
|
end
|
132
|
-
|
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
|
-
|
135
|
-
|
36
|
+
class_eval do
|
37
|
+
belongs_to association_name, polymorphic: true, dependent: :delete
|
136
38
|
|
137
|
-
|
138
|
-
|
39
|
+
alias_method :specific, association_name
|
40
|
+
alias_method :specific_class, :specific
|
139
41
|
|
140
|
-
def
|
141
|
-
|
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
|
-
|
144
|
-
|
145
|
-
|
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
|
-
|
57
|
+
alias_method :is_a_superclass, :acts_as_superclass
|
148
58
|
|
149
|
-
def
|
150
|
-
|
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
|
158
|
-
|
75
|
+
class Base
|
76
|
+
include ActsAsRelation
|
77
|
+
end
|
159
78
|
end
|