polymorpheus 3.1.1 → 3.4.0
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 +5 -5
- data/README.md +2 -14
- data/lib/polymorpheus/adapter.rb +5 -1
- data/lib/polymorpheus/interface/belongs_to_polymorphic.rb +1 -1
- data/lib/polymorpheus/interface/{rails4/has_many_as_polymorph.rb → has_many_as_polymorph.rb} +1 -1
- data/lib/polymorpheus/mysql_adapter.rb +1 -6
- data/lib/polymorpheus/version.rb +1 -1
- data/lib/polymorpheus.rb +1 -14
- data/polymorpheus.gemspec +4 -3
- data/spec/interface/belongs_to_polymorphic_spec.rb +44 -30
- data/spec/interface/has_many_as_polymorph_spec.rb +46 -29
- data/spec/interface/validates_polymorph_spec.rb +11 -9
- data/spec/interface_spec.rb +8 -8
- data/spec/schema_dumper_spec.rb +2 -2
- data/spec/spec_helper.rb +8 -7
- data/spec/support/connection_helpers.rb +0 -8
- data/spec/support/custom_matchers.rb +7 -7
- data/spec/support/schema_helpers.rb +1 -1
- data/spec/support/sql_query_subscriber.rb +17 -0
- data/spec/support/sql_test_helpers.rb +11 -13
- data/spec/trigger_spec.rb +30 -18
- metadata +17 -21
- data/lib/polymorpheus/interface/rails3/has_many_as_polymorph.rb +0 -29
- data/lib/polymorpheus/mysql_adapter/foreigner_constraints.rb +0 -30
- data/spec/support/active_record/connection_adapters/abstract_mysql_adapter.rb +0 -9
- data/spec/support/sql_logger.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 60273820617c2e5ef7e4eab45965a2729ae9ecb3e8ba05357cf9c0ae432d36be
|
4
|
+
data.tar.gz: 156743a57b80836a20280d0bdef6bd4e3f895e79cbf93aac60b986fe5deb4bac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bb967919da9877c1129879492445d4972aff408399c0c6da01804cc4848382e9565b1cf32aa72c63101cf791ef331e5382cededa0a146e0d439a828f34fade2
|
7
|
+
data.tar.gz: cb3b1f649f7317ef555b78b6932a5385c8f78ba7e8b5bbdb3d37a552a4b4c20dce0ef72fd1deb410745744885020766e674acd50a1826989b720fe99abe71e65
|
data/README.md
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
[](https://travis-ci.org/wegowise/polymorpheus)
|
2
1
|
[](https://codeclimate.com/github/wegowise/polymorpheus)
|
3
2
|
|
4
3
|
# Polymorpheus
|
@@ -10,15 +9,6 @@ no setup**
|
|
10
9
|
If you are using Bundler, you can add the gem to your Gemfile:
|
11
10
|
|
12
11
|
```ruby
|
13
|
-
# with Rails >= 4.2
|
14
|
-
gem 'polymorpheus'
|
15
|
-
```
|
16
|
-
|
17
|
-
Or:
|
18
|
-
|
19
|
-
```ruby
|
20
|
-
# with Rails < 4.2
|
21
|
-
gem 'foreigner'
|
22
12
|
gem 'polymorpheus'
|
23
13
|
```
|
24
14
|
|
@@ -142,8 +132,6 @@ Now let's review what we've done.
|
|
142
132
|
|
143
133
|
* Currently the gem only supports MySQL. Please feel free to fork and submit a
|
144
134
|
(well-tested) pull request if you want to add Postgres support.
|
145
|
-
* This gem is tested and has been tested for Rails 2.3.8, 3.0.x, 3.1.x, 3.2.x,
|
146
|
-
and 4.0.0
|
147
135
|
* For Rails 3.1+, you'll still need to use `up` and `down` methods in your
|
148
136
|
migrations.
|
149
137
|
|
@@ -214,8 +202,8 @@ pic.polymorpheus.query_condition
|
|
214
202
|
## Credits and License
|
215
203
|
|
216
204
|
* This gem was written by [Barun Singh](https://github.com/barunio)
|
217
|
-
*
|
218
|
-
the hood for Rails < 4.2.
|
205
|
+
* Older, unsupported versions of this gem use [Foreigner gem](https://github.com/matthuhiggins/foreigner)
|
206
|
+
under the hood for Rails < 4.2.
|
219
207
|
|
220
208
|
polymorpheus is Copyright © 2011-2015 Barun Singh and [WegoWise](
|
221
209
|
http://wegowise.com). It is free software, and may be redistributed under the
|
data/lib/polymorpheus/adapter.rb
CHANGED
@@ -15,7 +15,11 @@ module Polymorpheus
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def configured_adapter
|
18
|
-
ActiveRecord::Base.
|
18
|
+
if ActiveRecord::Base.respond_to?(:connection_db_config)
|
19
|
+
ActiveRecord::Base.connection_db_config.adapter # ActiveRecord >= 6.1
|
20
|
+
else
|
21
|
+
ActiveRecord::Base.connection_pool.spec.config[:adapter]
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
|
@@ -21,7 +21,7 @@ module Polymorpheus
|
|
21
21
|
|
22
22
|
# Set belongs_to associations
|
23
23
|
builder.associations.each do |association|
|
24
|
-
belongs_to association.name.to_sym, association.options
|
24
|
+
belongs_to association.name.to_sym, **association.options
|
25
25
|
end
|
26
26
|
|
27
27
|
# Exposed interface for introspection
|
@@ -74,7 +74,7 @@ module Polymorpheus
|
|
74
74
|
:name => "#{table}_#{col_name}_fk",
|
75
75
|
:primary_key => (ref_col || 'id' )
|
76
76
|
}.merge(generate_constraints(options))
|
77
|
-
add_foreign_key(table, ref_table, fk_options)
|
77
|
+
add_foreign_key(table, ref_table, **fk_options)
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -208,8 +208,3 @@ end
|
|
208
208
|
rescue
|
209
209
|
end
|
210
210
|
end
|
211
|
-
|
212
|
-
if ::Polymorpheus.require_foreigner?
|
213
|
-
require 'foreigner/connection_adapters/mysql2_adapter'
|
214
|
-
require 'polymorpheus/mysql_adapter/foreigner_constraints'
|
215
|
-
end
|
data/lib/polymorpheus/version.rb
CHANGED
data/lib/polymorpheus.rb
CHANGED
@@ -8,12 +8,7 @@ module Polymorpheus
|
|
8
8
|
module Interface
|
9
9
|
autoload :BelongsToPolymorphic, 'polymorpheus/interface/belongs_to_polymorphic'
|
10
10
|
autoload :ValidatesPolymorph, 'polymorpheus/interface/validates_polymorph'
|
11
|
-
|
12
|
-
if ActiveRecord::VERSION::MAJOR >= 4
|
13
|
-
autoload :HasManyAsPolymorph, 'polymorpheus/interface/rails4/has_many_as_polymorph'
|
14
|
-
else
|
15
|
-
autoload :HasManyAsPolymorph, 'polymorpheus/interface/rails3/has_many_as_polymorph'
|
16
|
-
end
|
11
|
+
autoload :HasManyAsPolymorph, 'polymorpheus/interface/has_many_as_polymorph'
|
17
12
|
end
|
18
13
|
|
19
14
|
class InterfaceBuilder
|
@@ -23,16 +18,8 @@ module Polymorpheus
|
|
23
18
|
module ConnectionAdapters
|
24
19
|
autoload :SchemaStatements, 'polymorpheus/schema_statements'
|
25
20
|
end
|
26
|
-
|
27
|
-
def self.require_foreigner?
|
28
|
-
ActiveRecord::VERSION::MAJOR < 5 &&
|
29
|
-
!(::ActiveRecord::VERSION::MAJOR >= 4 &&
|
30
|
-
::ActiveRecord::VERSION::MINOR >= 2)
|
31
|
-
end
|
32
21
|
end
|
33
22
|
|
34
|
-
require 'foreigner' if ::Polymorpheus.require_foreigner?
|
35
|
-
|
36
23
|
Polymorpheus::Adapter.register 'mysql2', 'polymorpheus/mysql_adapter'
|
37
24
|
Polymorpheus::Adapter.register 'postgresql', 'polymorpheus/postgresql_adapter'
|
38
25
|
|
data/polymorpheus.gemspec
CHANGED
@@ -12,13 +12,14 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = "Provides a database-friendly method for polymorphic relationships"
|
13
13
|
s.description = "Provides a database-friendly method for polymorphic relationships"
|
14
14
|
|
15
|
+
s.required_ruby_version = ">= 2.6"
|
15
16
|
s.required_rubygems_version = ">= 1.3.6"
|
16
17
|
s.files = Dir.glob(%w[{lib,spec}/**/*.rb [A-Z]*.{txt,rdoc,md} *.gemspec]) + %w{Rakefile}
|
17
18
|
s.extra_rdoc_files = ["README.md", "LICENSE.txt"]
|
18
19
|
s.license = 'MIT'
|
19
20
|
|
20
|
-
s.add_dependency('activerecord', '>=
|
21
|
+
s.add_dependency('activerecord', '>= 5.2', '< 7.1')
|
21
22
|
|
22
|
-
s.add_development_dependency('rake', '~>
|
23
|
-
s.add_development_dependency('rspec', '~>
|
23
|
+
s.add_development_dependency('rake', '~> 12.3.3')
|
24
|
+
s.add_development_dependency('rspec', '~> 3.9.0')
|
24
25
|
end
|
@@ -15,9 +15,12 @@ describe Polymorpheus::Interface::BelongsToPolymorphic do
|
|
15
15
|
create_table :villains
|
16
16
|
end
|
17
17
|
|
18
|
-
specify
|
19
|
-
|
20
|
-
|
18
|
+
specify do
|
19
|
+
expect(StoryArc::POLYMORPHEUS_ASSOCIATIONS).to eq(%w[hero villain])
|
20
|
+
end
|
21
|
+
specify do
|
22
|
+
expect(Superpower::POLYMORPHEUS_ASSOCIATIONS).to eq(%w[superhero supervillain])
|
23
|
+
end
|
21
24
|
|
22
25
|
describe "setter methods for ActiveRecord objects" do
|
23
26
|
let(:story_arc) { StoryArc.new(attributes) }
|
@@ -25,37 +28,38 @@ describe Polymorpheus::Interface::BelongsToPolymorphic do
|
|
25
28
|
|
26
29
|
it "sets the correct attribute value for the setter" do
|
27
30
|
story_arc.character = hero
|
28
|
-
story_arc.hero_id.
|
29
|
-
story_arc.villain_id.
|
31
|
+
expect(story_arc.hero_id).to eq(hero.id)
|
32
|
+
expect(story_arc.villain_id).to eq(nil)
|
30
33
|
end
|
31
34
|
|
32
35
|
it "sets competing associations to nil" do
|
33
36
|
story_arc.character = hero
|
34
|
-
story_arc.hero_id.
|
37
|
+
expect(story_arc.hero_id).to eq(hero.id)
|
35
38
|
story_arc.character = villain
|
36
|
-
story_arc.villain_id.
|
37
|
-
story_arc.hero_id.
|
39
|
+
expect(story_arc.villain_id).to eq(villain.id)
|
40
|
+
expect(story_arc.hero_id).to eq(nil)
|
38
41
|
end
|
39
42
|
|
40
43
|
it "throws an error if the assigned object isn't a valid type" do
|
41
44
|
create_table :trees
|
42
45
|
|
43
46
|
tree = Tree.create!
|
44
|
-
expect { story_arc.character = tree }
|
45
|
-
|
46
|
-
|
47
|
+
expect { story_arc.character = tree }.to raise_error(
|
48
|
+
Polymorpheus::Interface::InvalidTypeError,
|
49
|
+
"Invalid type. Must be one of {hero, villain}"
|
50
|
+
)
|
47
51
|
end
|
48
52
|
|
49
53
|
it "does not throw an error if the assigned object is a subclass of a
|
50
54
|
valid type" do
|
51
55
|
expect { story_arc.character = superhero }.not_to raise_error
|
52
|
-
story_arc.hero_id.
|
56
|
+
expect(story_arc.hero_id).to eq(superhero.id)
|
53
57
|
end
|
54
58
|
|
55
59
|
it "does not throw an error if the assigned object is a descendant of a
|
56
60
|
valid type" do
|
57
61
|
expect { story_arc.character = alien_demigod }.not_to raise_error
|
58
|
-
story_arc.hero_id.
|
62
|
+
expect(story_arc.hero_id).to eq(alien_demigod.id)
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
@@ -79,12 +83,12 @@ describe Polymorpheus::Interface::BelongsToPolymorphic do
|
|
79
83
|
|
80
84
|
it "works if the assigned object is of the specified class" do
|
81
85
|
expect { superpower.wielder = superhero }.not_to raise_error
|
82
|
-
superpower.superhero_id.
|
86
|
+
expect(superpower.superhero_id).to eq(superhero.id)
|
83
87
|
end
|
84
88
|
|
85
89
|
it "works if the assigned object is an instance of a child class" do
|
86
90
|
expect { superpower.wielder = alien_demigod }.not_to raise_error
|
87
|
-
superpower.superhero_id.
|
91
|
+
expect(superpower.superhero_id).to eq(alien_demigod.id)
|
88
92
|
end
|
89
93
|
end
|
90
94
|
|
@@ -94,42 +98,52 @@ describe Polymorpheus::Interface::BelongsToPolymorphic do
|
|
94
98
|
context 'when there is no relationship defined' do
|
95
99
|
let(:story_arc) { StoryArc.new }
|
96
100
|
|
97
|
-
|
98
|
-
|
99
|
-
|
101
|
+
specify do
|
102
|
+
expect(interface.associations).to match_associations(:hero, :villain)
|
103
|
+
end
|
104
|
+
specify { expect(interface.active_association).to eq nil }
|
105
|
+
specify { expect(interface.query_condition).to eq nil }
|
100
106
|
end
|
101
107
|
|
102
108
|
context 'when there is are multiple relationships defined' do
|
103
109
|
let(:story_arc) { StoryArc.new(hero_id: hero.id, villain_id: villain.id) }
|
104
110
|
|
105
|
-
|
106
|
-
|
107
|
-
|
111
|
+
specify do
|
112
|
+
expect(interface.associations).to match_associations(:hero, :villain)
|
113
|
+
end
|
114
|
+
specify { expect(interface.active_association).to eq nil }
|
115
|
+
specify { expect(interface.query_condition).to eq nil }
|
108
116
|
end
|
109
117
|
|
110
118
|
context 'when there is one relationship defined through the id value' do
|
111
119
|
let(:story_arc) { StoryArc.new(hero_id: hero.id) }
|
112
120
|
|
113
|
-
|
114
|
-
|
115
|
-
|
121
|
+
specify do
|
122
|
+
expect(interface.associations).to match_associations(:hero, :villain)
|
123
|
+
end
|
124
|
+
specify { expect(interface.active_association).to be_association(:hero) }
|
125
|
+
specify { expect(interface.query_condition).to eq('hero_id' => hero.id) }
|
116
126
|
end
|
117
127
|
|
118
128
|
context 'when there is one relationship defined through the setter' do
|
119
129
|
let(:story_arc) { StoryArc.new(character: hero) }
|
120
130
|
|
121
|
-
|
122
|
-
|
123
|
-
|
131
|
+
specify do
|
132
|
+
expect(interface.associations).to match_associations(:hero, :villain)
|
133
|
+
end
|
134
|
+
specify { expect(interface.active_association).to be_association(:hero) }
|
135
|
+
specify { expect(interface.query_condition).to eq('hero_id' => hero.id) }
|
124
136
|
end
|
125
137
|
|
126
138
|
context 'when there is one association, to a new record' do
|
127
139
|
let(:new_hero) { Hero.new }
|
128
140
|
let(:story_arc) { StoryArc.new(character: new_hero) }
|
129
141
|
|
130
|
-
|
131
|
-
|
132
|
-
|
142
|
+
specify do
|
143
|
+
expect(interface.associations).to match_associations(:hero, :villain)
|
144
|
+
end
|
145
|
+
specify { expect(interface.active_association).to be_association(:hero) }
|
146
|
+
specify { expect(interface.query_condition).to eq nil }
|
133
147
|
end
|
134
148
|
end
|
135
149
|
end
|
@@ -16,54 +16,71 @@ describe Polymorpheus::Interface::HasManyAsPolymorph do
|
|
16
16
|
|
17
17
|
it 'sets conditions on association to ensure we retrieve correct result' do
|
18
18
|
hero = Hero.create!
|
19
|
-
hero.story_arcs.to_sql
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
expect(hero.story_arcs.to_sql).to match_sql <<-EOS
|
20
|
+
SELECT `story_arcs`.* FROM `story_arcs`
|
21
|
+
WHERE `story_arcs`.`hero_id` = #{hero.id}
|
22
|
+
AND `story_arcs`.`villain_id` IS NULL
|
23
|
+
EOS
|
23
24
|
end
|
24
25
|
|
25
26
|
it 'supports existing conditions on the association' do
|
26
27
|
villain = Villain.create!
|
27
|
-
villain.story_arcs.to_sql
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
expect(villain.story_arcs.to_sql).to match_sql <<-EOS
|
29
|
+
SELECT `story_arcs`.* FROM `story_arcs`
|
30
|
+
WHERE `story_arcs`.`villain_id` = #{villain.id}
|
31
|
+
AND `story_arcs`.`hero_id` IS NULL
|
32
|
+
ORDER BY id DESC
|
33
|
+
EOS
|
32
34
|
end
|
33
35
|
|
34
36
|
it 'returns the correct result when used with new records' do
|
35
37
|
villain = Villain.create!
|
36
38
|
story_arc = StoryArc.create!(villain: villain, issue_id: 10)
|
37
|
-
Hero.new.story_arcs.where(issue_id: 10).
|
39
|
+
expect(Hero.new.story_arcs.where(issue_id: 10)).to eq([])
|
38
40
|
end
|
39
41
|
|
40
42
|
it 'sets conditions on associations with enough specificity that they work
|
41
43
|
in conjunction with has_many :through relationships' do
|
42
44
|
hero = Hero.create!
|
43
|
-
hero.battles.to_sql
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
expect(hero.battles.to_sql).to match_sql <<-EOS
|
46
|
+
SELECT `battles`.* FROM `battles`
|
47
|
+
INNER JOIN `story_arcs`
|
48
|
+
ON `battles`.`id` = `story_arcs`.`battle_id`
|
49
|
+
WHERE `story_arcs`.`hero_id` = #{hero.id}
|
50
|
+
AND `story_arcs`.`villain_id` IS NULL
|
51
|
+
EOS
|
49
52
|
end
|
50
53
|
|
51
54
|
it 'uses the correct association table name when used in conjunction with a
|
52
55
|
join condition' do
|
53
56
|
battle = Battle.create!
|
54
|
-
battle.heros.to_sql
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
expect(battle.heros.to_sql).to match_sql <<-EOS
|
58
|
+
SELECT `heros`.* FROM `heros`
|
59
|
+
INNER JOIN `story_arcs`
|
60
|
+
ON `heros`.`id` = `story_arcs`.`hero_id`
|
61
|
+
WHERE `story_arcs`.`battle_id` = #{battle.id}
|
62
|
+
EOS
|
59
63
|
|
60
|
-
|
61
|
-
.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
if ActiveRecord::VERSION::MAJOR >= 6
|
65
|
+
expect(battle.heros.joins(:story_arcs).to_sql).to match_sql <<-EOS
|
66
|
+
SELECT `heros`.* FROM `heros`
|
67
|
+
INNER JOIN `story_arcs`
|
68
|
+
ON `heros`.`id` = `story_arcs`.`hero_id`
|
69
|
+
INNER JOIN `story_arcs` `story_arcs_heros`
|
70
|
+
ON `story_arcs_heros`.`villain_id` IS NULL
|
71
|
+
AND `story_arcs_heros`.`hero_id` = `heros`.`id`
|
72
|
+
WHERE `story_arcs`.`battle_id` = #{battle.id}
|
73
|
+
EOS
|
74
|
+
else
|
75
|
+
expect(battle.heros.joins(:story_arcs).to_sql).to match_sql <<-EOS
|
76
|
+
SELECT `heros`.* FROM `heros`
|
77
|
+
INNER JOIN `story_arcs` `story_arcs_heros`
|
78
|
+
ON `story_arcs_heros`.`hero_id` = `heros`.`id`
|
79
|
+
AND `story_arcs_heros`.`villain_id` IS NULL
|
80
|
+
INNER JOIN `story_arcs`
|
81
|
+
ON `heros`.`id` = `story_arcs`.`hero_id`
|
82
|
+
WHERE `story_arcs`.`battle_id` = #{battle.id}
|
83
|
+
EOS
|
84
|
+
end
|
68
85
|
end
|
69
86
|
end
|
@@ -13,23 +13,25 @@ describe Polymorpheus::Interface::ValidatesPolymorph do
|
|
13
13
|
create_table(:villains)
|
14
14
|
end
|
15
15
|
|
16
|
-
specify { StoryArc.new(character: hero).valid
|
17
|
-
specify { StoryArc.new(character: villain).valid
|
18
|
-
specify { StoryArc.new(hero_id: hero.id).valid
|
19
|
-
specify { StoryArc.new(hero: hero).valid
|
20
|
-
specify { StoryArc.new(hero: Hero.new).valid
|
16
|
+
specify { expect(StoryArc.new(character: hero).valid?).to eq(true) }
|
17
|
+
specify { expect(StoryArc.new(character: villain).valid?).to eq(true) }
|
18
|
+
specify { expect(StoryArc.new(hero_id: hero.id).valid?).to eq(true) }
|
19
|
+
specify { expect(StoryArc.new(hero: hero).valid?).to eq(true) }
|
20
|
+
specify { expect(StoryArc.new(hero: Hero.new).valid?).to eq(true) }
|
21
21
|
|
22
22
|
it 'is invalid if no association is specified' do
|
23
23
|
story_arc = StoryArc.new
|
24
|
-
story_arc.valid
|
25
|
-
story_arc.errors[:base].
|
24
|
+
expect(story_arc.valid?).to eq(false)
|
25
|
+
expect(story_arc.errors[:base]).to eq(
|
26
26
|
["You must specify exactly one of the following: {hero, villain}"]
|
27
|
+
)
|
27
28
|
end
|
28
29
|
|
29
30
|
it 'is invalid if multiple associations are specified' do
|
30
31
|
story_arc = StoryArc.new(hero_id: hero.id, villain_id: villain.id)
|
31
|
-
story_arc.valid
|
32
|
-
story_arc.errors[:base].
|
32
|
+
expect(story_arc.valid?).to eq(false)
|
33
|
+
expect(story_arc.errors[:base]).to eq(
|
33
34
|
["You must specify exactly one of the following: {hero, villain}"]
|
35
|
+
)
|
34
36
|
end
|
35
37
|
end
|
data/spec/interface_spec.rb
CHANGED
@@ -7,10 +7,10 @@ describe Polymorpheus::Interface do
|
|
7
7
|
create_table :books
|
8
8
|
create_table :binders
|
9
9
|
|
10
|
-
Drawing.new.association(:book).reflection.inverse_of.
|
11
|
-
Drawing.new.association(:binder).reflection.inverse_of.
|
12
|
-
Book.new.association(:drawings).reflection.inverse_of.
|
13
|
-
Binder.new.association(:drawings).reflection.inverse_of.
|
10
|
+
expect(Drawing.new.association(:book).reflection.inverse_of).to eq(nil)
|
11
|
+
expect(Drawing.new.association(:binder).reflection.inverse_of).to eq(nil)
|
12
|
+
expect(Book.new.association(:drawings).reflection.inverse_of).to eq(nil)
|
13
|
+
expect(Binder.new.association(:drawings).reflection.inverse_of).to eq(nil)
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'with options' do
|
@@ -18,10 +18,10 @@ describe Polymorpheus::Interface do
|
|
18
18
|
create_table :web_pages
|
19
19
|
create_table :printed_works
|
20
20
|
|
21
|
-
Picture.new.association(:web_page).reflection.inverse_of.name.
|
22
|
-
Picture.new.association(:printed_work).reflection.inverse_of.name.
|
23
|
-
WebPage.new.association(:pictures).reflection.inverse_of.name.
|
24
|
-
PrintedWork.new.association(:pictures).reflection.inverse_of.name.
|
21
|
+
expect(Picture.new.association(:web_page).reflection.inverse_of.name).to eq(:pictures)
|
22
|
+
expect(Picture.new.association(:printed_work).reflection.inverse_of.name).to eq(:pictures)
|
23
|
+
expect(WebPage.new.association(:pictures).reflection.inverse_of.name).to eq(:web_page)
|
24
|
+
expect(PrintedWork.new.association(:pictures).reflection.inverse_of.name).to eq(:printed_work)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
data/spec/schema_dumper_spec.rb
CHANGED
@@ -30,10 +30,10 @@ describe Polymorpheus::SchemaDumper do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
specify "the schema statement is part of the dump" do
|
33
|
-
subject.index(schema_statement).
|
33
|
+
expect(subject.index(schema_statement)).to be_a(Integer)
|
34
34
|
end
|
35
35
|
|
36
36
|
specify "there is exactly one instance of the schema statement" do
|
37
|
-
subject.index(schema_statement).
|
37
|
+
expect(subject.index(schema_statement)).to eq(subject.rindex(schema_statement))
|
38
38
|
end
|
39
39
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,13 +2,14 @@ require 'active_record'
|
|
2
2
|
require 'polymorpheus'
|
3
3
|
require 'stringio'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
ActiveRecord::Base.establish_connection({
|
5
|
+
ActiveRecord::Base.establish_connection(
|
8
6
|
adapter: 'mysql2',
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
database: ENV.fetch('DB_NAME', 'polymorpheus_test'),
|
8
|
+
host: ENV.fetch('DB_HOST', '127.0.0.1'),
|
9
|
+
password: ENV.fetch('DB_PASSWORD', ''),
|
10
|
+
port: ENV.fetch('DB_PORT', '3306'),
|
11
|
+
username: ENV.fetch('DB_USERNAME', 'root')
|
12
|
+
)
|
12
13
|
|
13
14
|
Dir[File.dirname(__FILE__) + '/support/*.rb'].sort.each { |path| require path }
|
14
15
|
|
@@ -27,7 +28,7 @@ RSpec.configure do |config|
|
|
27
28
|
config.include SqlTestHelpers
|
28
29
|
|
29
30
|
config.after do
|
30
|
-
|
31
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
31
32
|
ActiveRecord::Base.connection.drop_table(table)
|
32
33
|
end
|
33
34
|
end
|
@@ -3,14 +3,6 @@ module ConnectionHelpers
|
|
3
3
|
connection.add_polymorphic_constraints(*args)
|
4
4
|
end
|
5
5
|
|
6
|
-
def data_sources
|
7
|
-
if ActiveRecord::VERSION::MAJOR >= 5
|
8
|
-
ActiveRecord::Base.connection.data_sources
|
9
|
-
else
|
10
|
-
ActiveRecord::Base.connection.tables
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
6
|
def remove_polymorphic_constraints(*args)
|
15
7
|
connection.remove_polymorphic_constraints(*args)
|
16
8
|
end
|
@@ -1,31 +1,31 @@
|
|
1
1
|
RSpec::Matchers.define :be_association do |association_name|
|
2
2
|
match do |actual|
|
3
|
-
actual.
|
4
|
-
actual.name.
|
3
|
+
expect(actual).to be_instance_of Polymorpheus::InterfaceBuilder::Association
|
4
|
+
expect(actual.name).to eq association_name.to_s
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
8
|
RSpec::Matchers.define :match_associations do |*association_names|
|
9
9
|
match do |actual|
|
10
|
-
actual.length.
|
10
|
+
expect(actual.length).to eq association_names.length
|
11
11
|
actual.each_with_index do |item, ind|
|
12
|
-
item.
|
12
|
+
expect(item).to be_association(association_names[ind])
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
RSpec::Matchers.define :match_sql do |expected|
|
18
18
|
match do |actual|
|
19
|
-
format(expected).
|
19
|
+
expect(format(expected)).to eq format(actual)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
failure_message do |actual|
|
23
23
|
"expected the following SQL statements to match:
|
24
24
|
#{format(actual)}
|
25
25
|
#{format(expected)}"
|
26
26
|
end
|
27
27
|
|
28
28
|
def format(sql)
|
29
|
-
sql.
|
29
|
+
sql.squish
|
30
30
|
end
|
31
31
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Polymorpheus
|
2
|
+
class SqlQuerySubscriber
|
3
|
+
attr_reader :sql_statements
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@sql_statements = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(_name, _start, _finish, _id, payload)
|
10
|
+
sql_statements << payload[:sql]
|
11
|
+
end
|
12
|
+
|
13
|
+
def clear_sql_history
|
14
|
+
@sql_statements.clear
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -2,22 +2,16 @@ module SqlTestHelpers
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
included do
|
5
|
-
before
|
6
|
-
|
7
|
-
include Polymorpheus::SqlLogger
|
8
|
-
alias_method :original_execute, :execute
|
9
|
-
alias_method :execute, :log_sql_statements
|
10
|
-
end
|
5
|
+
before do
|
6
|
+
ActiveSupport::Notifications.subscribe('sql.active_record', sql_logger)
|
11
7
|
end
|
12
8
|
|
13
|
-
after
|
14
|
-
|
15
|
-
alias_method :execute, :original_execute
|
16
|
-
end
|
9
|
+
after do
|
10
|
+
ActiveSupport::Notifications.unsubscribe(sql_logger)
|
17
11
|
end
|
18
12
|
|
19
13
|
let(:connection) { ActiveRecord::Base.connection }
|
20
|
-
let(:
|
14
|
+
let(:sql_logger) { Polymorpheus::SqlQuerySubscriber.new }
|
21
15
|
|
22
16
|
def clean_sql(sql_string)
|
23
17
|
sql_string
|
@@ -31,11 +25,15 @@ module SqlTestHelpers
|
|
31
25
|
end
|
32
26
|
|
33
27
|
def clear_sql_history
|
34
|
-
|
28
|
+
sql_logger.clear_sql_history
|
35
29
|
end
|
36
30
|
|
37
31
|
def should_execute_sql(expected)
|
38
|
-
expect(clean_sql(sql.join("\n"))).to include(clean_sql(expected
|
32
|
+
expect(clean_sql(sql.join("\n"))).to include(clean_sql(expected))
|
33
|
+
end
|
34
|
+
|
35
|
+
def sql
|
36
|
+
sql_logger.sql_statements
|
39
37
|
end
|
40
38
|
end
|
41
39
|
end
|
data/spec/trigger_spec.rb
CHANGED
@@ -19,27 +19,39 @@ describe Polymorpheus::Trigger do
|
|
19
19
|
let(:collation_connection) { "utf8_general_ci" }
|
20
20
|
let(:db_collation) { "utf8_unicode_ci" }
|
21
21
|
|
22
|
-
|
23
|
-
described_class.new(
|
24
|
-
|
25
|
-
|
22
|
+
let(:trigger) do
|
23
|
+
described_class.new(
|
24
|
+
[
|
25
|
+
name,
|
26
|
+
event,
|
27
|
+
table,
|
28
|
+
statement,
|
29
|
+
timing,
|
30
|
+
created,
|
31
|
+
sql_mode,
|
32
|
+
definer,
|
33
|
+
charset,
|
34
|
+
collation_connection,
|
35
|
+
db_collation
|
36
|
+
]
|
37
|
+
)
|
26
38
|
end
|
27
39
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
specify { expect(trigger.name).to eq name }
|
41
|
+
specify { expect(trigger.event).to eq event }
|
42
|
+
specify { expect(trigger.table).to eq table }
|
43
|
+
specify { expect(trigger.statement).to eq statement }
|
44
|
+
specify { expect(trigger.timing).to eq timing }
|
45
|
+
specify { expect(trigger.created).to eq created }
|
46
|
+
specify { expect(trigger.sql_mode).to eq sql_mode }
|
47
|
+
specify { expect(trigger.definer).to eq definer }
|
48
|
+
specify { expect(trigger.charset).to eq charset }
|
49
|
+
specify { expect(trigger.collation_connection).to eq collation_connection }
|
50
|
+
specify { expect(trigger.db_collation).to eq db_collation }
|
39
51
|
|
40
|
-
|
52
|
+
specify { expect(trigger.columns).to eq %w[dog_id kitty_id] }
|
41
53
|
|
42
|
-
|
43
|
-
|
54
|
+
specify do
|
55
|
+
expect(trigger.schema_statement).to eq %{ add_polymorphic_triggers(:pets, ["dog_id", "kitty_id"])}
|
44
56
|
end
|
45
57
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: polymorpheus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Barun Singh
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,48 +16,48 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.2'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7.1'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '5.2'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: rake
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
39
|
+
version: 12.3.3
|
40
40
|
type: :development
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
46
|
+
version: 12.3.3
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
53
|
+
version: 3.9.0
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
60
|
+
version: 3.9.0
|
61
61
|
description: Provides a database-friendly method for polymorphic relationships
|
62
62
|
email: bsingh@wegowise.com
|
63
63
|
executables: []
|
@@ -73,13 +73,11 @@ files:
|
|
73
73
|
- lib/polymorpheus/adapter.rb
|
74
74
|
- lib/polymorpheus/interface.rb
|
75
75
|
- lib/polymorpheus/interface/belongs_to_polymorphic.rb
|
76
|
-
- lib/polymorpheus/interface/
|
77
|
-
- lib/polymorpheus/interface/rails4/has_many_as_polymorph.rb
|
76
|
+
- lib/polymorpheus/interface/has_many_as_polymorph.rb
|
78
77
|
- lib/polymorpheus/interface/validates_polymorph.rb
|
79
78
|
- lib/polymorpheus/interface_builder.rb
|
80
79
|
- lib/polymorpheus/interface_builder/association.rb
|
81
80
|
- lib/polymorpheus/mysql_adapter.rb
|
82
|
-
- lib/polymorpheus/mysql_adapter/foreigner_constraints.rb
|
83
81
|
- lib/polymorpheus/postgresql_adapter.rb
|
84
82
|
- lib/polymorpheus/railtie.rb
|
85
83
|
- lib/polymorpheus/schema_dumper.rb
|
@@ -94,19 +92,18 @@ files:
|
|
94
92
|
- spec/mysql2_adapter_spec.rb
|
95
93
|
- spec/schema_dumper_spec.rb
|
96
94
|
- spec/spec_helper.rb
|
97
|
-
- spec/support/active_record/connection_adapters/abstract_mysql_adapter.rb
|
98
95
|
- spec/support/class_defs.rb
|
99
96
|
- spec/support/connection_helpers.rb
|
100
97
|
- spec/support/custom_matchers.rb
|
101
98
|
- spec/support/schema_helpers.rb
|
102
|
-
- spec/support/
|
99
|
+
- spec/support/sql_query_subscriber.rb
|
103
100
|
- spec/support/sql_test_helpers.rb
|
104
101
|
- spec/trigger_spec.rb
|
105
102
|
homepage: http://github.com/wegowise/polymorpheus
|
106
103
|
licenses:
|
107
104
|
- MIT
|
108
105
|
metadata: {}
|
109
|
-
post_install_message:
|
106
|
+
post_install_message:
|
110
107
|
rdoc_options: []
|
111
108
|
require_paths:
|
112
109
|
- lib
|
@@ -114,16 +111,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
114
111
|
requirements:
|
115
112
|
- - ">="
|
116
113
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
114
|
+
version: '2.6'
|
118
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
116
|
requirements:
|
120
117
|
- - ">="
|
121
118
|
- !ruby/object:Gem::Version
|
122
119
|
version: 1.3.6
|
123
120
|
requirements: []
|
124
|
-
|
125
|
-
|
126
|
-
signing_key:
|
121
|
+
rubygems_version: 3.3.6
|
122
|
+
signing_key:
|
127
123
|
specification_version: 4
|
128
124
|
summary: Provides a database-friendly method for polymorphic relationships
|
129
125
|
test_files: []
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module Polymorpheus
|
2
|
-
module Interface
|
3
|
-
module HasManyAsPolymorph
|
4
|
-
def has_many_as_polymorph(association, options = {})
|
5
|
-
options.symbolize_keys!
|
6
|
-
fkey = name.foreign_key
|
7
|
-
|
8
|
-
class_name = options[:class_name] || association.to_s.classify
|
9
|
-
|
10
|
-
options[:conditions] = proc do
|
11
|
-
keys = class_name.constantize
|
12
|
-
.const_get('POLYMORPHEUS_ASSOCIATIONS')
|
13
|
-
.map(&:foreign_key)
|
14
|
-
keys.delete(fkey)
|
15
|
-
|
16
|
-
nil_columns = keys.reduce({}) { |hash, key| hash.merge!(key => nil) }
|
17
|
-
|
18
|
-
if self.is_a?(ActiveRecord::Associations::JoinDependency::JoinAssociation)
|
19
|
-
{ aliased_table_name => nil_columns }
|
20
|
-
else
|
21
|
-
{ association => nil_columns }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
has_many association, options
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module Polymorpheus
|
2
|
-
module ConnectionAdapters
|
3
|
-
module MysqlAdapter
|
4
|
-
def generate_constraints(options)
|
5
|
-
constraints = []
|
6
|
-
|
7
|
-
['delete', 'update'].each do |event|
|
8
|
-
option = "on_#{event}".to_sym
|
9
|
-
next unless options.has_key?(option) &&
|
10
|
-
options[option].respond_to?(:to_sym)
|
11
|
-
|
12
|
-
action = case options[option].to_sym
|
13
|
-
when :nullify then 'SET NULL'
|
14
|
-
when :cascade then 'CASCADE'
|
15
|
-
when :restrict then 'RESTRICT'
|
16
|
-
else
|
17
|
-
fail ArgumentError, <<-EOS
|
18
|
-
'#{options[option]}' is not supported for :on_update or :on_delete.
|
19
|
-
Supported values are: :nullify, :cascade, :restrict
|
20
|
-
EOS
|
21
|
-
end
|
22
|
-
|
23
|
-
constraints << "ON #{event.upcase} #{action}"
|
24
|
-
end
|
25
|
-
|
26
|
-
{ :options => constraints.join(' ') }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
# Patch support for MySQL 5.7+ onto ActiveRecord < 4.1.
|
2
|
-
if ActiveRecord::VERSION::MAJOR < 4 ||
|
3
|
-
(ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR < 1)
|
4
|
-
|
5
|
-
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
6
|
-
class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
|
7
|
-
NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
|
8
|
-
end
|
9
|
-
end
|
data/spec/support/sql_logger.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
module Polymorpheus
|
2
|
-
module SqlLogger
|
3
|
-
|
4
|
-
def sql_statements
|
5
|
-
@sql_statements ||= []
|
6
|
-
end
|
7
|
-
|
8
|
-
def clear_sql_history
|
9
|
-
@sql_statements = nil
|
10
|
-
end
|
11
|
-
|
12
|
-
def stub_sql(statement, response)
|
13
|
-
@stubbed ||= {}
|
14
|
-
@stubbed[statement] = response
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def log_sql_statements(sql, name = nil)
|
20
|
-
if @stubbed && @stubbed.has_key?(sql)
|
21
|
-
@stubbed[sql]
|
22
|
-
else
|
23
|
-
sql_statements << sql
|
24
|
-
original_execute(sql, name)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|