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