Skip to content

Commit 579e97c

Browse files
committed
raw type should be able to deserialize
ActiveRecord expects types to properly deserialize any values that have been serialized. Right now (Rails 7.1) by every object save the attributes are reset by serialize/deserialize cycle. see ActiveModel::ActiveModel#forget_attribute_assignments
1 parent 9638d46 commit 579e97c

File tree

2 files changed

+39
-4
lines changed
  • lib/active_record/type/oracle_enhanced
  • spec/active_record/oracle_enhanced/type

2 files changed

+39
-4
lines changed

lib/active_record/type/oracle_enhanced/raw.rb

+19-2
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,31 @@ def type
1010
:raw
1111
end
1212

13+
def deserialize(value)
14+
value.is_a?(HEXData) ? value.raw_binary_string : super
15+
end
16+
1317
def serialize(value)
1418
# Encode a string or byte array as string of hex codes
1519
if value.nil?
1620
super
1721
else
18-
value = value.unpack("C*")
19-
value.map { |x| "%02X" % x }.join
22+
HEXData.from_binary_string(value)
23+
end
24+
end
25+
26+
class HEXData < ::String
27+
def self.from_binary_string(str)
28+
new(str.unpack1("H*"))
29+
end
30+
31+
def raw_binary_string
32+
(0..length - 2).step(2).reduce(::String.new(capacity: length/2, encoding: Encoding::BINARY)) do |data, i|
33+
data << self[i, 2].hex
34+
end
2035
end
36+
37+
OCI8::BindType::Mapping[self] = OCI8::BindType::String
2138
end
2239
end
2340
end

spec/active_record/oracle_enhanced/type/raw_spec.rb

+20-2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class ::TestEmployee < ActiveRecord::Base
3838
last_name: "Last",
3939
binary_data: @binary_data
4040
)
41+
expect(@employee.binary_data).to eq(@binary_data)
4142
@employee.reload
4243
expect(@employee.binary_data).to eq(@binary_data)
4344
end
@@ -51,6 +52,7 @@ class ::TestEmployee < ActiveRecord::Base
5152
expect(@employee.binary_data).to be_nil
5253
@employee.binary_data = @binary_data
5354
@employee.save!
55+
expect(@employee.binary_data).to eq(@binary_data)
5456
@employee.reload
5557
expect(@employee.binary_data).to eq(@binary_data)
5658
end
@@ -77,6 +79,7 @@ class ::TestEmployee < ActiveRecord::Base
7779
@employee.reload
7880
@employee.binary_data = @binary_data2
7981
@employee.save!
82+
expect(@employee.binary_data).to eq(@binary_data2)
8083
@employee.reload
8184
expect(@employee.binary_data).to eq(@binary_data2)
8285
end
@@ -116,13 +119,14 @@ class ::TestEmployee < ActiveRecord::Base
116119
@employee.reload
117120
@employee.binary_data = @binary_data
118121
@employee.save!
122+
expect(@employee.binary_data).to eq(@binary_data)
119123
@employee.reload
120124
expect(@employee.binary_data).to eq(@binary_data)
121125
end
122126

123127
it "should allow equality on select" do
124128
TestEmployee.delete_all
125-
TestEmployee.create!(
129+
employee = TestEmployee.create!(
126130
first_name: "First",
127131
last_name: "Last",
128132
binary_data: @binary_data,
@@ -132,6 +136,20 @@ class ::TestEmployee < ActiveRecord::Base
132136
last_name: "Last1",
133137
binary_data: @binary_data2,
134138
)
135-
expect(TestEmployee.where(binary_data: @binary_data)).to have_attributes(count: 1)
139+
expect(TestEmployee.where(binary_data: @binary_data).to_a).to eq([employee])
140+
end
141+
142+
it "should allow equality on select with NULL value" do
143+
TestEmployee.delete_all
144+
employee = TestEmployee.create!(
145+
first_name: "First",
146+
last_name: "Last",
147+
)
148+
TestEmployee.create!(
149+
first_name: "First1",
150+
last_name: "Last1",
151+
binary_data: @binary_data2,
152+
)
153+
expect(TestEmployee.where(binary_data: nil).to_a).to eq([employee])
136154
end
137155
end

0 commit comments

Comments
 (0)