Skip to content

Commit 506ee4b

Browse files
authored
Fix enum defined on string columns (#1059)
Fixes #1042 varchar, varchar_max and text sql server types extends from char (`ActiveRecord::ConnectionAdapters::SQLServer::Type:Char`). `ActiveRecord::ConnectionAdapters::SQLServer::Type::Char.serialize` return an `ActiveRecord::ConnectionAdapters::SQLServer::Type::Data` instance. `Data` defines ``` def eql?(other) self.class == other.class && value == other.value end ``` Let's imagine the following ActiveRecord definition ``` class MyRecord < ActiveRecord::Base enum release: { alpha: "A", beta: "B" } end ``` When we call `my_record.alpha?` it compares `release` serialized value with the string "A". It will be always false because `Data` and `String` clases are different. This commit reimplements `eql?` to deal with string arguments.
1 parent e714ae3 commit 506ee4b

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- [#1052](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1052) Ignore casing of VALUES clause when inserting records using SQL
66
- [#1053](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1053) Fix insertion of records to non-default schema table using raw SQL
7+
- [#1059](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1059) Fix enums defined on string columns
78

89
## v7.0.2.0
910

lib/active_record/connection_adapters/sqlserver/type/data.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ def inspect
2727
end
2828

2929
def eql?(other)
30+
# Support comparing `Type::Char`, `Type::Varchar` and `VarcharMax` with strings.
31+
# This happens when we use enum with string columns.
32+
if other.is_a?(::String)
33+
return type.is_a?(ActiveRecord::ConnectionAdapters::SQLServer::Type::String) && value == other
34+
end
35+
3036
self.class == other.class && value == other.value
3137
end
3238
alias :== :eql?

test/cases/enum_test_sqlserver.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# frozen_string_literal: true
2+
3+
require "cases/helper_sqlserver"
4+
5+
class EnumTestSQLServer < ActiveRecord::TestCase
6+
7+
# Check that enums are supported for all string types.
8+
# For each type we check: cast, serialize, and update by declaration.
9+
# We create a custom class for each type to test.
10+
%w[char_10 varchar_50 varchar_max text nchar_10 nvarchar_50 nvarchar_max ntext].each do |col_name|
11+
describe "support #{col_name} enums" do
12+
let(:klass) do
13+
Class.new(ActiveRecord::Base) do
14+
self.table_name = 'sst_datatypes'
15+
16+
enum col_name => { alpha: "A", beta: "B" }
17+
end
18+
end
19+
20+
it "type.cast" do
21+
type = klass.type_for_attribute(col_name)
22+
23+
assert_equal "alpha", type.cast('A')
24+
assert_equal "beta", type.cast('B')
25+
end
26+
27+
it "type.serialize" do
28+
type = klass.type_for_attribute(col_name)
29+
30+
assert_equal 'A', type.serialize('A')
31+
assert_equal 'B', type.serialize('B')
32+
33+
assert_equal 'A', type.serialize(:alpha)
34+
assert_equal 'B', type.serialize(:beta)
35+
end
36+
37+
it "update by declaration" do
38+
r = klass.new
39+
40+
r.alpha!
41+
assert_predicate r, :alpha?
42+
43+
r.beta!
44+
assert_not_predicate r, :alpha?
45+
assert_predicate r, :beta?
46+
end
47+
end
48+
end
49+
end

0 commit comments

Comments
 (0)