You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The succ call described in #854 fails to match when the type column being used in STI is an enumerable, because that column's values are restricted.
Reproduction Steps
Modify the below reproduction script to match a locally running Postgres install, and then run it.
require'bundler/inline'gemfile(true)dosource'https://rubygems.org'gem'shoulda-matchers'gem'activerecord'gem'pg'gem'rspec'endrequire'active_record'require'shoulda-matchers'require'logger'ActiveRecord::Base.establish_connection(adapter: 'pg',database: 'YOUR_LOCATION_HERE')ActiveRecord::Base.logger=Logger.new(STDOUT)# TODO: Update the schema to include the specific tables or columns necessary# to reproduct the bugActiveRecord::Schema.definedocreate_enum"big_model_types",["BigModel","LittleModel"]create_table:big_models,force: truedo |t|
t.enum"type",default: "BigModel",null: false,enum_type: "big_model_types"endcreate_table"model_fields",force: :cascadedo |t|
t.string"name",null: falset.string"record_type",null: falset.bigint"record_id",null: falseendendShoulda::Matchers.configuredo |config|
config.integratedo |with|
with.test_framework:rspecwith.library:active_recordwith.library:active_modelendendRSpec.configuredo |config|
config.includeShoulda::Matchers::ActiveRecordconfig.includeShoulda::Matchers::ActiveModelconfig.includeShoulda::Matchers::ActionControllerend# TODO: Add any application specific code necessary to reproduce the bugclassBigModel < ActiveRecord::Basehas_one:some_model_field,->{where(name: 'some')},as: :record,autosave: true,class_name: 'ModelField',dependent: :destroy,inverse_of: :recordendclassModelField < ActiveRecord::Basebelongs_to:record,polymorphic: true,optional: falsevalidates:name,presence: true,uniqueness: {scope: [:record_id,:record_type]}end# typed: falseFactoryBot.definedofactory:model_fielddoname{"my_field_name"}endend# TODO: Write a failing test case to demonstrate what isn't working as# expectedRSpec.describeModelFielddodescribe"name + record uniqueness"dosubject{build(:model_field,record: nil)}before{create(:model_field,record: nil)}let(:record){create(:big_model)}it{is_expected.tovalidate_uniqueness_of(:name).scoped_to([:record_id,:record_type])}endend
Expected behavior
Validation passes.
Actual behavior
1) ModelField validations name + record uniqueness is expected to validate that :name is case-sensitively unique within the scope of :record_id and :record_type
Failure/Error: it { is_expected.to validate_uniqueness_of(:name).scoped_to([:record_id, :record_type]) }
ActiveRecord::StatementInvalid:
PG::InvalidTextRepresentation: ERROR: invalid input value for enum big_model_types: "Shoulda::Matchers::ActiveRecord::Uniqueness::TestModels::BigModem"
LINE 1: ...g_models" WHERE "big_models"."type" = 'Shoulda::...
^
# ./spec/models/model_field_spec.rb:17:in `block (4 levels) in <main>'
# -e:1:in `<main>'
# ------------------
# --- Caused by: ---
# PG::InvalidTextRepresentation:
# ERROR: invalid input value for enum big_model_types: "Shoulda::Matchers::ActiveRecord::Uniqueness::TestModels::BigModem"
# LINE 1: ...g_models" WHERE "big_models"."type" = 'Shoulda::...
# ^
# ./spec/models/model_field_spec.rb:17:in `block (4 levels) in <main>'
Hi, thanks for the report! Unfortunately, we can't do much in that case, as the defined values are only stored in the database. I searched for an interface to access those values in the Rails adapters, but it does not exist (so it could work for any database adapter); it might be something nice to add on Rails itself.
If I have some free time, I can try to move that forward in Rails, but I can't promise as I don't have much time now.
Would it work to add a manual override in the matcher API? Something like validate_uniqueness_of(attr, valid_names_to_try)? Then we could tell the matcher the other names it should try instead of going to the succ call.
Would it work to add a manual override in the matcher API? Something like validate_uniqueness_of(attr, valid_names_to_try)? Then we could tell the matcher the other names it should try instead of going to the succ call.
Yes, that's an excellent idea. I'll put that on my backlog of features!
Description
The
succ
call described in #854 fails to match when thetype
column being used in STI is an enumerable, because that column's values are restricted.Reproduction Steps
Modify the below reproduction script to match a locally running Postgres install, and then run it.
Expected behavior
Validation passes.
Actual behavior
System configuration
shoulda_matchers version: 6.2.0
rails version: 7.1.3.2
ruby version: 3.2.1
The text was updated successfully, but these errors were encountered: