Created
September 5, 2025 04:40
-
-
Save jessevdp/12bc703048e7cf8ec8b0ba3e7728bc31 to your computer and use it in GitHub Desktop.
StoreModel array unique validation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class MyModel | |
| attribute :my_array_of_store_models, MyStoreModel.to_array_type, default: -> { [] } | |
| validates :my_array_of_store_models, | |
| store_model: true, | |
| "store_model_validators/unique": { attrs: [:name] } | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class MyStoreModel | |
| include StoreModel::Model | |
| attribute :name, :string | |
| validates :name, presence: true | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class StoreModelValidatators::UniqueValidator < ActiveModel::EachValidator | |
| def validate_each(record, attribute, value) | |
| options[:attrs].each do |validated_attribute| | |
| AttributeUniqueValidatorInstance.new( | |
| record:, | |
| collection_attribute: attribute, | |
| collection: value, | |
| attribute: validated_attribute | |
| ).validate | |
| end | |
| end | |
| class AttributeUniqueValidatorInstance | |
| def initialize(record:, collection_attribute:, collection:, attribute:) | |
| @record = record | |
| @collection_attribute = collection_attribute | |
| @collection = collection | |
| @attribute = attribute | |
| end | |
| def validate | |
| add_duplicate_error if duplicate_attribute_values.any? | |
| end | |
| private | |
| def duplicate_attribute_values | |
| all_attribute_values | |
| .select { |value| all_attribute_values.count(value) > 1 } | |
| .uniq | |
| end | |
| def all_attribute_values = @collection.pluck(@attribute) | |
| def add_duplicate_error | |
| message = "can't contain duplicate #{@attribute}s (duplicates: #{duplicate_attribute_values.join(', ')})" | |
| @record.errors.add(@collection_attribute, error_type, message:) | |
| end | |
| def error_type = :"duplicate_#{@attribute}" | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment