Skip to content

Commit f77fc1e

Browse files
committed
write attribute with polymorphic integer type
1 parent 40e2b27 commit f77fc1e

File tree

5 files changed

+68
-3
lines changed

5 files changed

+68
-3
lines changed

lib/polymorphic_integer_type.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
require "polymorphic_integer_type/module_generator"
77
require "polymorphic_integer_type/belongs_to_polymorphic_association_extension"
88
require "polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension"
9+
require "polymorphic_integer_type/polymorphic_foreign_association_extension"
910

1011
if ACTIVE_RECORD_VERSION < Gem::Version.new("5.2.0")
1112
require "polymorphic_integer_type/activerecord_5_0_0/association_query_handler_extension"

lib/polymorphic_integer_type/extensions.rb

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ def remove_type_and_establish_mapping(name, options, scope)
5858

5959
options[:foreign_key] ||= "#{poly_type}_id"
6060
foreign_type = options.delete(:foreign_type) || "#{poly_type}_type"
61+
options[:foreign_integer_type] = foreign_type
62+
options[:integer_type] = klass_mapping.to_i
6163

6264
options[:scope] ||= -> {
6365
condition = where(foreign_type => klass_mapping.to_i)
@@ -87,7 +89,9 @@ def has_many(name, scope = nil, **options, &extension)
8789
end
8890

8991
remove_type_and_establish_mapping(name, options, scope)
90-
super(name, options.delete(:scope), **options, &extension)
92+
super(name, options.delete(:scope), **options.except(:foreign_integer_type, :integer_type), &extension).tap do |_|
93+
remove_integer_type_and_set_attributes_and_extension(options, ActiveRecord::Reflection::HasManyReflection, reflections[name.to_s])
94+
end
9195
end
9296

9397
def has_one(name, scope = nil, **options)
@@ -97,7 +101,28 @@ def has_one(name, scope = nil, **options)
97101
end
98102

99103
remove_type_and_establish_mapping(name, options, scope)
100-
super(name, options.delete(:scope), **options)
104+
super(name, options.delete(:scope), **options.except(:foreign_integer_type, :integer_type)).tap do |_|
105+
remove_integer_type_and_set_attributes_and_extension(options, ActiveRecord::Reflection::HasOneReflection, reflections[name.to_s])
106+
end
107+
end
108+
109+
def remove_integer_type_and_set_attributes_and_extension(options, klass, reflection)
110+
foreign_integer_type = options.delete :foreign_integer_type
111+
integer_type = options.delete :integer_type
112+
is_polymorphic_integer = foreign_integer_type && integer_type
113+
114+
if is_polymorphic_integer
115+
klass.attr_accessor(:foreign_integer_type)
116+
klass.attr_accessor(:integer_type)
117+
reflection.foreign_integer_type = foreign_integer_type
118+
reflection.integer_type = integer_type
119+
120+
if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("6.1")
121+
ActiveRecord::Associations::Association.prepend(ActiveRecord::Associations::PolymorphicForeignAssociationExtension)
122+
else
123+
ActiveRecord::Associations::ForeignAssociation.prepend(ActiveRecord::Associations::PolymorphicForeignAssociationExtension)
124+
end
125+
end
101126
end
102127

103128

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module ActiveRecord
2+
module Associations
3+
module PolymorphicForeignAssociationExtension
4+
5+
def set_owner_attributes(record)
6+
super
7+
if reflection.foreign_integer_type && reflection.integer_type
8+
record._write_attribute(reflection.foreign_integer_type, reflection.integer_type)
9+
end
10+
end
11+
end
12+
end
13+
end

spec/polymorphic_integer_type_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,28 @@
2626
expect(link.target_type).to eq("Food")
2727
end
2828

29+
context "from HasManyReflection" do
30+
it "sets the source properly from HasManyReflection" do
31+
link_1 = Link.create()
32+
link_2 = Link.create()
33+
dog.source_links = [link_1, link_2]
34+
expect(link_1.source_type).to eq("Animal")
35+
expect(link_1.source_id).to eq(dog.id)
36+
expect(link_2.source_type).to eq("Animal")
37+
expect(link_1.source_id).to eq(dog.id)
38+
end
39+
end
40+
41+
context "from HasOneReflection" do
42+
it "sets the source properly from HasManyReflection" do
43+
link = Link.create()
44+
dog.source_link = link
45+
46+
expect(link.source_type).to eq("Animal")
47+
expect(link.source_id).to eq(dog.id)
48+
end
49+
end
50+
2951
context "when models are namespaced" do
3052
context "and mappings include namespaces" do
3153
it "sets the source_type" do
@@ -340,6 +362,10 @@ class InlineDrink2 < ActiveRecord::Base
340362
expect(link[:target_type]).to eq(13)
341363
end
342364

365+
it "pulls mapping from given hash" do
366+
animal.source_links.new
367+
end
368+
343369
it "doesn't break string type polymorphic associations" do
344370
expect(link.normal_target).to eq(drink)
345371
expect(link.normal_target_type).to eq("InlineDrink2")

spec/support/animal.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ class Animal < ActiveRecord::Base
33

44
belongs_to :owner, class_name: "Person"
55
has_many :source_links, as: :source, integer_type: true, class_name: "Link"
6-
6+
has_one :source_link, as: :source, integer_type: true, class_name: "Link"
77
end

0 commit comments

Comments
 (0)