Commit 41ee09c9 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'blackst0ne-rails5-fix-type-cast-for-from-database' into 'master'

[Rails5] Update `type_cast_*_database`  methods

See merge request gitlab-org/gitlab-ce!18188
parents 52b232ca 20695052
...@@ -17,7 +17,7 @@ class MergeRequestDiffCommit < ActiveRecord::Base ...@@ -17,7 +17,7 @@ class MergeRequestDiffCommit < ActiveRecord::Base
commit_hash.merge( commit_hash.merge(
merge_request_diff_id: merge_request_diff_id, merge_request_diff_id: merge_request_diff_id,
relative_order: index, relative_order: index,
sha: sha_attribute.type_cast_for_database(sha), sha: sha_attribute.serialize(sha), # rubocop:disable Cop/ActiveRecordSerialize
authored_date: Gitlab::Database.sanitize_timestamp(commit_hash[:authored_date]), authored_date: Gitlab::Database.sanitize_timestamp(commit_hash[:authored_date]),
committed_date: Gitlab::Database.sanitize_timestamp(commit_hash[:committed_date]) committed_date: Gitlab::Database.sanitize_timestamp(commit_hash[:committed_date])
) )
......
module ActiveRecord # Remove this initializer when upgraded to Rails 5.0
class PredicateBuilder unless Gitlab.rails5?
class ArrayHandler module ActiveRecord
module TypeCasting class PredicateBuilder
def call(attribute, value) class ArrayHandler
# This is necessary because by default ActiveRecord does not respect module TypeCasting
# custom type definitions (like our `ShaAttribute`) when providing an def call(attribute, value)
# array in `where`, like in `where(commit_sha: [sha1, sha2, sha3])`. # This is necessary because by default ActiveRecord does not respect
model = attribute.relation&.engine # custom type definitions (like our `ShaAttribute`) when providing an
type = model.user_provided_columns[attribute.name] if model # array in `where`, like in `where(commit_sha: [sha1, sha2, sha3])`.
value = value.map { |value| type.type_cast_for_database(value) } if type model = attribute.relation&.engine
type = model.user_provided_columns[attribute.name] if model
value = value.map { |value| type.type_cast_for_database(value) } if type
super(attribute, value) super(attribute, value)
end
end end
end
prepend TypeCasting prepend TypeCasting
end
end end
end end
end end
...@@ -96,7 +96,7 @@ module Gitlab ...@@ -96,7 +96,7 @@ module Gitlab
commit_hash.merge( commit_hash.merge(
merge_request_diff_id: merge_request_diff.id, merge_request_diff_id: merge_request_diff.id,
relative_order: index, relative_order: index,
sha: sha_attribute.type_cast_for_database(sha) sha: sha_attribute.serialize(sha)
) )
end end
......
module Gitlab module Gitlab
module Database module Database
BINARY_TYPE = if Gitlab::Database.postgresql? BINARY_TYPE =
# PostgreSQL defines its own class with slightly different if Gitlab::Database.postgresql?
# behaviour from the default Binary type. # PostgreSQL defines its own class with slightly different
ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Bytea # behaviour from the default Binary type.
else ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Bytea
ActiveRecord::Type::Binary else
end # In Rails 5.0 `Type` has been moved from `ActiveRecord` to `ActiveModel`
# https://github.com/rails/rails/commit/9cc8c6f3730df3d94c81a55be9ee1b7b4ffd29f6#diff-f8ba7983a51d687976e115adcd95822b
# Remove this method and leave just `ActiveModel::Type::Binary` when removing Gitlab.rails5? code.
if Gitlab.rails5?
ActiveModel::Type::Binary
else
ActiveRecord::Type::Binary
end
end
# Class for casting binary data to hexadecimal SHA1 hashes (and vice-versa). # Class for casting binary data to hexadecimal SHA1 hashes (and vice-versa).
# #
...@@ -16,18 +24,39 @@ module Gitlab ...@@ -16,18 +24,39 @@ module Gitlab
class ShaAttribute < BINARY_TYPE class ShaAttribute < BINARY_TYPE
PACK_FORMAT = 'H*'.freeze PACK_FORMAT = 'H*'.freeze
# Casts binary data to a SHA1 in hexadecimal. # It is called from activerecord-4.2.10/lib/active_record internal methods.
# Remove this method when removing Gitlab.rails5? code.
def type_cast_from_database(value) def type_cast_from_database(value)
value = super unpack_sha(super)
end
# It is called from activerecord-4.2.10/lib/active_record internal methods.
# Remove this method when removing Gitlab.rails5? code.
def type_cast_for_database(value)
serialize(value)
end
# It is called from activerecord-5.0.6/lib/active_record/attribute.rb
# Remove this method when removing Gitlab.rails5? code..
def deserialize(value)
value = Gitlab.rails5? ? super : method(:type_cast_from_database).super_method.call(value)
unpack_sha(value)
end
# Rename this method to `deserialize(value)` removing Gitlab.rails5? code.
# Casts binary data to a SHA1 in hexadecimal.
def unpack_sha(value)
# Uncomment this line when removing Gitlab.rails5? code.
# value = super
value ? value.unpack(PACK_FORMAT)[0] : nil value ? value.unpack(PACK_FORMAT)[0] : nil
end end
# Casts a SHA1 in hexadecimal to the proper binary format. # Casts a SHA1 in hexadecimal to the proper binary format.
def type_cast_for_database(value) def serialize(value)
arg = value ? [value].pack(PACK_FORMAT) : nil arg = value ? [value].pack(PACK_FORMAT) : nil
super(arg) Gitlab.rails5? ? super(arg) : method(:type_cast_for_database).super_method.call(arg)
end end
end end
end end
......
...@@ -19,15 +19,15 @@ describe Gitlab::Database::ShaAttribute do ...@@ -19,15 +19,15 @@ describe Gitlab::Database::ShaAttribute do
let(:attribute) { described_class.new } let(:attribute) { described_class.new }
describe '#type_cast_from_database' do describe '#deserialize' do
it 'converts the binary SHA to a String' do it 'converts the binary SHA to a String' do
expect(attribute.type_cast_from_database(binary_from_db)).to eq(sha) expect(attribute.deserialize(binary_from_db)).to eq(sha)
end end
end end
describe '#type_cast_for_database' do describe '#serialize' do
it 'converts a SHA String to binary data' do it 'converts a SHA String to binary data' do
expect(attribute.type_cast_for_database(sha).to_s).to eq(binary_sha) expect(attribute.serialize(sha).to_s).to eq(binary_sha)
end end
end end
end end
...@@ -36,7 +36,7 @@ describe MergeRequestDiffCommit do ...@@ -36,7 +36,7 @@ describe MergeRequestDiffCommit do
"committer_email": "dmitriy.zaporozhets@gmail.com", "committer_email": "dmitriy.zaporozhets@gmail.com",
"merge_request_diff_id": merge_request_diff_id, "merge_request_diff_id": merge_request_diff_id,
"relative_order": 0, "relative_order": 0,
"sha": sha_attribute.type_cast_for_database('5937ac0a7beb003549fc5fd26fc247adbce4a52e') "sha": sha_attribute.serialize("5937ac0a7beb003549fc5fd26fc247adbce4a52e")
}, },
{ {
"message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", "message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n",
...@@ -48,7 +48,7 @@ describe MergeRequestDiffCommit do ...@@ -48,7 +48,7 @@ describe MergeRequestDiffCommit do
"committer_email": "dmitriy.zaporozhets@gmail.com", "committer_email": "dmitriy.zaporozhets@gmail.com",
"merge_request_diff_id": merge_request_diff_id, "merge_request_diff_id": merge_request_diff_id,
"relative_order": 1, "relative_order": 1,
"sha": sha_attribute.type_cast_for_database('570e7b2abdd848b95f2f578043fc23bd6f6fd24d') "sha": sha_attribute.serialize("570e7b2abdd848b95f2f578043fc23bd6f6fd24d")
} }
] ]
end end
...@@ -79,7 +79,7 @@ describe MergeRequestDiffCommit do ...@@ -79,7 +79,7 @@ describe MergeRequestDiffCommit do
"committer_email": "alejorro70@gmail.com", "committer_email": "alejorro70@gmail.com",
"merge_request_diff_id": merge_request_diff_id, "merge_request_diff_id": merge_request_diff_id,
"relative_order": 0, "relative_order": 0,
"sha": sha_attribute.type_cast_for_database('ba3343bc4fa403a8dfbfcab7fc1a8c29ee34bd69') "sha": sha_attribute.serialize("ba3343bc4fa403a8dfbfcab7fc1a8c29ee34bd69")
}] }]
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment