Skip to content

Commit aabb91f

Browse files
committed
all attributes serialized before writing
1 parent 5a158ed commit aabb91f

File tree

2 files changed

+91
-5
lines changed

2 files changed

+91
-5
lines changed

lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,9 @@ def write_lobs(table_name, klass, attributes, columns) #:nodoc:
255255
value = attributes[col.name]
256256
# changed sequence of next two lines - should check if value is nil before converting to yaml
257257
next unless value
258-
if klass.attribute_types[col.name].is_a? Type::Serialized
259-
value = klass.attribute_types[col.name].serialize(value)
260-
# value can be nil after serialization because ActiveRecord serializes [] and {} as nil
261-
next unless value
262-
end
258+
value = klass.attribute_types[col.name].serialize(value)
259+
# value can be nil after serialization because ActiveRecord serializes [] and {} as nil
260+
next unless value
263261
uncached do
264262
unless lob_record = select_one(sql = <<~SQL.squish, "Writable Large Object")
265263
SELECT #{quote_column_name(col.name)} FROM #{quote_table_name(table_name)}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# frozen_string_literal: true
2+
3+
describe "OracleEnhancedAdapter custom types handling" do
4+
include SchemaSpecHelper
5+
6+
before(:all) do
7+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
8+
schema_define do
9+
create_table :test_employees, force: true do |t|
10+
t.string :first_name, limit: 20
11+
t.string :last_name, limit: 25
12+
t.text :signature
13+
end
14+
end
15+
16+
class TestEmployee < ActiveRecord::Base
17+
class AttributeSignature < ActiveRecord::Type::Text
18+
def cast(value)
19+
case value
20+
when Signature
21+
value
22+
when nil
23+
nil
24+
else
25+
Signature.new(Base64.decode64 value)
26+
end
27+
end
28+
29+
def serialize(value)
30+
Base64.encode64 value.raw
31+
end
32+
33+
def changed_in_place?(raw_old_value, new_value)
34+
new_value != cast(raw_old_value)
35+
end
36+
end
37+
38+
class Signature
39+
attr_reader :raw
40+
41+
def initialize(raw_value)
42+
@raw = raw_value
43+
end
44+
45+
def to_s
46+
"Signature nice string #{raw[0..5]}"
47+
end
48+
49+
def ==(object)
50+
raw == object&.raw
51+
end
52+
alias eql? ==
53+
end
54+
55+
attribute :signature, AttributeSignature.new
56+
end
57+
end
58+
59+
after(:all) do
60+
schema_define do
61+
drop_table :test_employees
62+
end
63+
Object.send(:remove_const, "TestEmployee")
64+
ActiveRecord::Base.clear_cache!
65+
end
66+
67+
it "should serialize LOBs when creating a record" do
68+
raw_signature = "peter'ssignature"
69+
signature = TestEmployee::Signature.new(raw_signature)
70+
@employee = TestEmployee.create!(first_name: "Peter", last_name: "Doe", signature: signature)
71+
@employee.reload
72+
expect(@employee.signature).to eql(signature)
73+
expect(@employee.signature).to_not be(signature)
74+
expect(TestEmployee.first.read_attribute_before_type_cast(:signature)).to eq(Base64.encode64 raw_signature)
75+
end
76+
77+
it "should serialize LOBs when updating a record" do
78+
raw_signature = "peter'ssignature"
79+
signature = TestEmployee::Signature.new(raw_signature)
80+
@employee = TestEmployee.create!(first_name: "Peter", last_name: "Doe", signature: TestEmployee::Signature.new("old signature"))
81+
@employee.signature = signature
82+
@employee.save!
83+
@employee.reload
84+
expect(@employee.signature).to eql(signature)
85+
expect(@employee.signature).to_not be(signature)
86+
expect(TestEmployee.first.read_attribute_before_type_cast(:signature)).to eq(Base64.encode64 raw_signature)
87+
end
88+
end

0 commit comments

Comments
 (0)