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
@@ -0,0 +1,63 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ActsAsRelation
|
3
|
+
module AccessMethods
|
4
|
+
def define_acts_as_accessors(model_name)
|
5
|
+
# The weird order of the if-else branches is so that we query ourselves
|
6
|
+
# before we query our superclass.
|
7
|
+
class_eval <<-EndCode, __FILE__, __LINE__ + 1
|
8
|
+
def read_attribute(attr_name, *args, &proc)
|
9
|
+
if attribute_method?(attr_name)
|
10
|
+
super(attr_name, *args)
|
11
|
+
else
|
12
|
+
#{model_name}.read_attribute(attr_name, *args, &proc)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def attributes
|
17
|
+
if #{model_name}.changed? || changed?
|
18
|
+
@attributes = #{model_name}.attributes.merge(super)
|
19
|
+
else
|
20
|
+
@attributes ||= #{model_name}.attributes.merge(super)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def attributes=(new_attributes)
|
25
|
+
sub = new_attributes.select { |k,v| attribute_method?(k) }
|
26
|
+
sup = new_attributes.select { |k,v| !attribute_method?(k) }
|
27
|
+
super(sub)
|
28
|
+
#{model_name}.attributes = sup
|
29
|
+
end
|
30
|
+
|
31
|
+
def touch(name = nil, *args, &proc)
|
32
|
+
if attribute_method?(name.to_s)
|
33
|
+
super(name, *args, &proc)
|
34
|
+
else
|
35
|
+
super(nil, *args, &proc)
|
36
|
+
#{model_name}.touch(name, *args, &proc)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def save(*args)
|
41
|
+
super(*args) && #{model_name}.save(*args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def save!(*args)
|
45
|
+
super(*args) && #{model_name}.save!(*args)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def write_attribute(attr_name, *args, &proc)
|
51
|
+
if attribute_method?(attr_name.to_s)
|
52
|
+
super(attr_name, *args)
|
53
|
+
else
|
54
|
+
#{model_name}.send(:write_attribute, attr_name, *args, &proc)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
EndCode
|
58
|
+
end
|
59
|
+
|
60
|
+
protected :define_acts_as_accessors
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ActsAsRelation
|
3
|
+
class ActsAs
|
4
|
+
attr_accessor :module
|
5
|
+
attr_reader :name, :class_name, :model, :association_name, :module_name, :module_name, :scope, :options
|
6
|
+
|
7
|
+
def initialize(model_name, scope = nil, options = {})
|
8
|
+
@model_name = model_name
|
9
|
+
@options, @scope = scope.is_a?(Hash) ? [scope, nil] : [options, scope]
|
10
|
+
|
11
|
+
@name = @model_name.to_s.underscore.singularize.to_sym
|
12
|
+
@class_name = @options[:class_name] || @name.to_s.camelcase
|
13
|
+
@model = @class_name.constantize
|
14
|
+
@association_name = @options[:as] || @model.acts_as_association_name
|
15
|
+
@module_name = "ActsAs#{name.to_s.camelcase}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def parent_relations
|
19
|
+
@parent_relations ||= (model.reflect_on_all_associations.map(&:name) - [association_name]).map { |a| a.to_s + '_id' }
|
20
|
+
end
|
21
|
+
|
22
|
+
def has_one_options
|
23
|
+
@has_one_options ||= {
|
24
|
+
as: association_name,
|
25
|
+
class_name: class_name,
|
26
|
+
inverse_of: association_name.to_sym,
|
27
|
+
autosave: true,
|
28
|
+
validate: false,
|
29
|
+
dependent: options.fetch(:dependent, :destroy)
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ActsAsRelation
|
3
|
+
module ActsAsModules
|
4
|
+
class << self
|
5
|
+
def [](acts_as)
|
6
|
+
if const_defined? acts_as.module_name
|
7
|
+
const_get acts_as.module_name
|
8
|
+
else
|
9
|
+
acts_as_module = Module.new
|
10
|
+
const_set acts_as.module_name, acts_as_module
|
11
|
+
acts_as.module = acts_as_module
|
12
|
+
create_assocication(acts_as)
|
13
|
+
autobuild_superclass(acts_as)
|
14
|
+
validate_superclass(acts_as)
|
15
|
+
make_superclass_methods_accessible(acts_as)
|
16
|
+
make_superclass_attributes_accessible(acts_as)
|
17
|
+
fix_is_a(acts_as)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_assocication(acts_as)
|
22
|
+
acts_as.module.extend ActiveSupport::Concern
|
23
|
+
acts_as.module.included do
|
24
|
+
has_one acts_as.name, acts_as.scope, acts_as.has_one_options
|
25
|
+
alias_method_chain acts_as.name, :autobuild
|
26
|
+
|
27
|
+
validate "#{acts_as.name}_must_be_valid".to_sym
|
28
|
+
|
29
|
+
extend ActiveRecord::ActsAsRelation::AccessMethods
|
30
|
+
define_acts_as_accessors(acts_as.name)
|
31
|
+
|
32
|
+
if defined?(::ProtectedAttributes)
|
33
|
+
attr_accessible.update(acts_as.model.attr_accessible)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def autobuild_superclass(acts_as)
|
39
|
+
acts_as.module.module_eval do
|
40
|
+
define_method "#{acts_as.name}_with_autobuild" do
|
41
|
+
send("#{acts_as.name}_without_autobuild") || send("build_#{acts_as.name}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def make_superclass_methods_accessible(acts_as)
|
47
|
+
acts_as.module.module_eval do
|
48
|
+
define_method :method_missing do |method, *arg, &block|
|
49
|
+
if (method.to_s == 'id' || method.to_s == acts_as.name) || !send(acts_as.name).respond_to?(method)
|
50
|
+
super(method, *arg, &block)
|
51
|
+
else
|
52
|
+
class_eval do
|
53
|
+
delegate method, to: acts_as.name
|
54
|
+
end
|
55
|
+
send(acts_as.name).send(method, *arg, &block)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
define_method :respond_to? do |method, include_private_methods = false|
|
60
|
+
super(method, include_private_methods) || send(acts_as.name).respond_to?(method, include_private_methods)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def fix_is_a(acts_as)
|
66
|
+
acts_as.module.module_eval do
|
67
|
+
define_method :is_a? do |klass|
|
68
|
+
klass.name == acts_as.class_name ? true : super(klass)
|
69
|
+
end
|
70
|
+
alias_method :acts_as?, :is_a?
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def make_superclass_attributes_accessible(acts_as)
|
75
|
+
acts_as.module.module_eval do
|
76
|
+
define_method :[] do |key|
|
77
|
+
if acts_as.parent_relations.include?(key.to_s)
|
78
|
+
send(acts_as.name)[key]
|
79
|
+
else
|
80
|
+
super(key)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
define_method :[]= do |key, value|
|
85
|
+
if acts_as.parent_relations.include?(key.to_s)
|
86
|
+
send(acts_as.name)[key] = value
|
87
|
+
else
|
88
|
+
super(key, value)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def validate_superclass(acts_as)
|
95
|
+
acts_as.module.module_eval do
|
96
|
+
define_method "#{acts_as.name}_must_be_valid" do
|
97
|
+
unless send(acts_as.name).valid?
|
98
|
+
send(acts_as.name).errors.each do |att, message|
|
99
|
+
errors.add(att, message)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
protected "#{acts_as.name}_must_be_valid".to_sym
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ActsAsRelation
|
3
|
+
module SuperclassMigration
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
alias_method_chain :create_table, :as_relation_superclass
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_table_with_as_relation_superclass(table_name, options = {})
|
11
|
+
create_table_without_as_relation_superclass(table_name, options) do |t|
|
12
|
+
if options.key? :as_relation_superclass
|
13
|
+
name = options[:as_relation_superclass]
|
14
|
+
if name == true
|
15
|
+
name = ActiveRecord::Base.acts_as_association_name table_name
|
16
|
+
end
|
17
|
+
|
18
|
+
t.integer "#{name}_id"
|
19
|
+
t.string "#{name}_type"
|
20
|
+
t.index ["#{name}_id", "#{name}_type"], name: "#{table_name}_#{name}_index"
|
21
|
+
end
|
22
|
+
|
23
|
+
yield t if block_given?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module ConnectionAdapters::SchemaStatements
|
30
|
+
include ActsAsRelation::SuperclassMigration
|
31
|
+
end
|
32
|
+
end
|
data/lib/acts_as_relation.rb
CHANGED
@@ -1,2 +1,5 @@
|
|
1
1
|
require 'active_record/acts_as_relation'
|
2
|
-
require 'active_record/
|
2
|
+
require 'active_record/acts_as_relation/acts_as'
|
3
|
+
require 'active_record/acts_as_relation/access_methods'
|
4
|
+
require 'active_record/acts_as_relation/acts_as_modules'
|
5
|
+
require 'active_record/acts_as_relation/superclass_migration'
|
data/lib/version.rb
CHANGED
@@ -1,43 +1,62 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
it
|
3
|
+
describe 'Submodel' do
|
4
|
+
it 'respond to supermodel attributes' do
|
5
5
|
pen = Pen.new
|
6
|
-
|
7
|
-
|
8
|
-
pen = Pen.create :name => 'RedPen', :price => 0.8, :color => 'red'
|
9
|
-
pen.should respond_to(m)
|
6
|
+
%w(name name= name_changed? name_was price price= price_changed? price_was).each do |at|
|
7
|
+
expect(pen).to respond_to(at)
|
10
8
|
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns supermodel attributes with #attributes' do
|
12
|
+
pen = Pen.new
|
13
|
+
expect(pen.attributes.keys).to include(*%w(name price))
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'makes supermodel attributes assingeable through #attributes=' do
|
17
|
+
pen = Pen.new
|
18
|
+
pen.attributes = {name: 'test', price: 10, color: 'black'}
|
19
|
+
expect(pen.name).to eq('test')
|
20
|
+
expect(pen.price).to eq(10)
|
21
|
+
expect(pen.color).to eq('black')
|
22
|
+
end
|
11
23
|
|
12
|
-
|
13
|
-
pen.name
|
14
|
-
pen.
|
15
|
-
pen.
|
24
|
+
it 'accept supermodel attributes on create' do
|
25
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
26
|
+
expect(pen.name).to eq('RedPen')
|
27
|
+
expect(pen.price).to eq(0.8)
|
28
|
+
expect(pen.color).to eq('red')
|
16
29
|
|
17
30
|
pen.price = 0.9
|
18
|
-
pen.price_changed
|
19
|
-
pen.price_was.
|
31
|
+
expect(pen.price_changed?).to be true
|
32
|
+
expect(pen.price_was).to eq(0.8)
|
20
33
|
end
|
21
34
|
|
22
|
-
it
|
23
|
-
store = Store.create :
|
24
|
-
pen = Pen.create :
|
35
|
+
it 'inherits Supermodel associations' do
|
36
|
+
store = Store.create name: 'Big Store'
|
37
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
25
38
|
pen.store = store
|
26
39
|
pen.save
|
27
|
-
Pen.find(pen.id).store.
|
28
|
-
Pen.find(pen.id).product.store.
|
40
|
+
expect(Pen.find(pen.id).store).to eq(store)
|
41
|
+
expect(Pen.find(pen.id).product.store).to eq(store)
|
29
42
|
end
|
30
43
|
|
31
|
-
it
|
44
|
+
it 'inherits Supermodel validations' do
|
32
45
|
pen = Pen.new
|
33
|
-
pen.
|
34
|
-
pen.errors.keys.
|
46
|
+
expect(pen).to be_invalid
|
47
|
+
expect(pen.errors.keys).to include(:name, :price, :color)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'inherits Supermodel methods' do
|
51
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
52
|
+
expect(pen).to respond_to('parent_method')
|
53
|
+
expect(pen.parent_method).to eq('RedPen - 0.8')
|
35
54
|
end
|
36
55
|
|
37
|
-
it
|
38
|
-
pen = Pen.create :
|
39
|
-
pen.
|
40
|
-
pen.
|
56
|
+
it 'raise NoMethodError correctly for Supermodel methods' do
|
57
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
58
|
+
expect(pen).to respond_to('dummy_raise_method')
|
59
|
+
expect { pen.dummy_raise_method(nil) }.to raise_error(NoMethodError, /undefined method `dummy' for nil:NilClass/)
|
41
60
|
end
|
42
61
|
|
43
62
|
# it "inherits Supermodel dynamic finders" do
|
@@ -47,72 +66,130 @@ describe "Submodel" do
|
|
47
66
|
# Product.find_by_name('SomeProduct').should == product
|
48
67
|
# end
|
49
68
|
|
50
|
-
it
|
51
|
-
pen = Pen.create :
|
52
|
-
|
69
|
+
it 'should raise NoMethodEror on unexisting method calls' do
|
70
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
71
|
+
expect { pen.unexisted_method }.to raise_error(NoMethodError)
|
53
72
|
end
|
54
73
|
|
55
|
-
it
|
56
|
-
pen = Pen.create :
|
74
|
+
it 'destroies Supermodel on destroy' do
|
75
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
57
76
|
product_id = pen.product.id
|
58
77
|
pen.destroy
|
59
|
-
|
78
|
+
expect { Product.find product_id }.to raise_error(ActiveRecord::RecordNotFound)
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#acts_as_other_model?' do
|
82
|
+
it 'return true on models wich acts_as other ones' do
|
83
|
+
expect(Pen.acts_as_other_model?).to be true
|
84
|
+
end
|
60
85
|
end
|
61
86
|
|
62
|
-
describe
|
63
|
-
it
|
64
|
-
Pen.
|
87
|
+
describe '#acts_as_model_name' do
|
88
|
+
it 'returns name of model wich it acts as' do
|
89
|
+
expect(Pen.acts_as_model_name).to eq(:product)
|
65
90
|
end
|
66
91
|
end
|
67
92
|
|
68
|
-
describe
|
69
|
-
it
|
70
|
-
|
93
|
+
describe '#is_a?' do
|
94
|
+
it 'should return true when the supermodel is passed' do
|
95
|
+
product = Product.new
|
96
|
+
expect(product.is_a?(Product)).to be true
|
97
|
+
expect(product.instance_of?(Product)).to be true
|
98
|
+
expect(product.is_a?(Product)).to be true
|
99
|
+
expect(product.acts_as?(Product)).to be true
|
100
|
+
expect(product.acts_as?(String)).to be false
|
101
|
+
|
102
|
+
pen = Pen.new
|
103
|
+
expect(pen.is_a?(Product)).to be true
|
104
|
+
expect(pen.instance_of?(Product)).to be true
|
105
|
+
expect(pen.is_a?(Product)).to be true
|
106
|
+
expect(pen.acts_as?(Product)).to be true
|
107
|
+
expect(pen.acts_as?(Store)).to be false
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should return true when the supermodel is passed to model' do
|
111
|
+
expect(Pen.acts_as? Product).to be true
|
112
|
+
expect(Pen.acts_as? String).to be false
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'in a has_many relation' do
|
117
|
+
it 'should be appendable using << operator' do
|
118
|
+
store = Store.create(name: 'Big Store')
|
119
|
+
pen = Pen.create(name: 'RedPen', price: 0.8, color: 'red')
|
120
|
+
store.products << pen
|
121
|
+
expect(pen.store).to eq(store)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should access child attributes' do
|
125
|
+
store = Store.create(name: 'Big Store')
|
126
|
+
pen = Pen.create(name: 'RedPen', price: 0.8, color: 'red')
|
127
|
+
store.products << pen
|
128
|
+
store.reload
|
129
|
+
expect(store.products.first.is_a?(Pen)).to be true
|
130
|
+
expect(store.products.first).to eq(pen)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'associate relation on saving superclass object' do
|
134
|
+
store = Store.new(name: 'Big Store')
|
135
|
+
pen = Pen.new(name: 'RedPen', price: 0.8, color: 'red')
|
136
|
+
store.products << pen
|
137
|
+
store.save
|
138
|
+
store.reload
|
139
|
+
expect(store.products.first).to eq(pen)
|
71
140
|
end
|
72
141
|
end
|
73
142
|
|
74
|
-
it
|
143
|
+
it 'have supermodel attr_accessibles as attr_accessibles' do
|
75
144
|
if defined?(::ProtectedAttributes)
|
76
145
|
Pen.attr_accessible[:default].each do |a|
|
77
|
-
Pencil.attr_accessible[:default].
|
146
|
+
expect(Pencil.attr_accessible[:default]).to include(a)
|
78
147
|
end
|
79
148
|
end
|
80
149
|
end
|
81
150
|
|
82
|
-
it
|
83
|
-
pen = Pen.create :
|
151
|
+
it 'should be findable' do
|
152
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
84
153
|
pen = Pen.find(pen.id)
|
85
|
-
pen.
|
154
|
+
expect(pen).to be_valid
|
86
155
|
end
|
87
156
|
|
88
|
-
it
|
89
|
-
pen = Pen.create :
|
157
|
+
it 'should be saveable' do
|
158
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
90
159
|
pen = Pen.find(pen.id)
|
91
|
-
|
160
|
+
expect { pen.save }.not_to raise_error
|
92
161
|
end
|
93
162
|
|
94
|
-
describe
|
95
|
-
describe
|
96
|
-
it
|
97
|
-
pen = Pen.create :
|
98
|
-
Pen.create :
|
99
|
-
Pen.create :
|
100
|
-
|
101
|
-
Pen.where(
|
163
|
+
describe 'Query Interface' do
|
164
|
+
describe 'auto_join' do
|
165
|
+
it 'automaticaly joins Supermodel on Submodel queries' do
|
166
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
167
|
+
Pen.create name: 'RedPen2', price: 1.2, color: 'red'
|
168
|
+
Pen.create name: 'BluePen', price: 1.2, color: 'blue'
|
169
|
+
expect { Pen.where('price > 1').to_a }.not_to raise_error
|
170
|
+
expect(Pen.where('name = ?', 'RedPen')).to include(pen)
|
102
171
|
end
|
103
172
|
|
104
|
-
it
|
105
|
-
|
173
|
+
it 'can be disabled by setting auto_join option to false' do
|
174
|
+
expect { Pencil.where('name = 1').to_a }.to raise_error(ActiveRecord::StatementInvalid)
|
106
175
|
end
|
107
176
|
end
|
108
177
|
end
|
109
178
|
end
|
110
179
|
|
111
|
-
describe
|
112
|
-
describe
|
113
|
-
it
|
114
|
-
pen = Pen.create :
|
115
|
-
pen.product.specific.
|
180
|
+
describe 'Supermodel' do
|
181
|
+
describe '#specific' do
|
182
|
+
it 'returns the specific subclass object' do
|
183
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
184
|
+
expect(pen.product.specific).to eq(pen)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'on destroy' do
|
189
|
+
it 'deletes specific subclass' do
|
190
|
+
pen = Pen.create name: 'RedPen', price: 0.8, color: 'red'
|
191
|
+
pen.product.destroy
|
192
|
+
expect { pen.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
116
193
|
end
|
117
194
|
end
|
118
195
|
end
|