dry-validation: Case insensitive `included_in?` validation with Dry::Validation.Schema












0















I'm trying to create a validation for a predetermined list of valid brands as part of an ETL pipeline. My validation requires case insensitivity, as some brands are compound words or abbreviations that are insignificant.



I created a custom predicate, but I cannot figure out how to generate the appropriate error message.



I read the error messages doc, but am having a hard time interpreting:




  • How to build the syntax for my custom predicate?

  • Can I apply the messages in my schema class directly, without referencing an external .yml file? I looked here and it seems like it's not as straightforward as I'd hoped.


Below I've given code that represents what I have tried using both built-in predicates, and a custom one, each with their own issues. If there is a better way to compose a rule that achieves the same goal, I'd love to learn it.



require 'dry/validation'

CaseSensitiveSchema = Dry::Validation.Schema do
BRANDS = %w(several hundred valid brands)

# :included_in? from https://dry-rb.org/gems/dry-validation/basics/built-in-predicates/
required(:brand).value(included_in?: BRANDS)
end

CaseInsensitiveSchema = Dry::Validation.Schema do
BRANDS = %w(several hundred valid brands)

configure do
def in_brand_list?(value)
BRANDS.include? value.downcase
end
end

required(:brand).value(:in_brand_list?)
end


# A valid string if case insensitive
valid_product = {brand: 'Valid'}

CaseSensitiveSchema.call(valid_product).errors
# => {:brand=>["must be one of: here, are, some, valid, brands"]} # This message will be ridiculous when the full brand list is applied

CaseInsensitiveSchema.call(valid_product).errors
# => {} # Good!



invalid_product = {brand: 'Junk'}

CaseSensitiveSchema.call(invalid_product).errors
# => {:brand=>["must be one of: several, hundred, valid, brands"]} # Good... (Except this error message will contain the entire brand list!!!)

CaseInsensitiveSchema.call(invalid_product).errors
# => Dry::Validation::MissingMessageError: message for in_brand_list? was not found
# => from .. /gems/2.5.0/gems/dry-validation-0.12.2/lib/dry/validation/message_compiler.rb:116:in `visit_predicate'









share|improve this question



























    0















    I'm trying to create a validation for a predetermined list of valid brands as part of an ETL pipeline. My validation requires case insensitivity, as some brands are compound words or abbreviations that are insignificant.



    I created a custom predicate, but I cannot figure out how to generate the appropriate error message.



    I read the error messages doc, but am having a hard time interpreting:




    • How to build the syntax for my custom predicate?

    • Can I apply the messages in my schema class directly, without referencing an external .yml file? I looked here and it seems like it's not as straightforward as I'd hoped.


    Below I've given code that represents what I have tried using both built-in predicates, and a custom one, each with their own issues. If there is a better way to compose a rule that achieves the same goal, I'd love to learn it.



    require 'dry/validation'

    CaseSensitiveSchema = Dry::Validation.Schema do
    BRANDS = %w(several hundred valid brands)

    # :included_in? from https://dry-rb.org/gems/dry-validation/basics/built-in-predicates/
    required(:brand).value(included_in?: BRANDS)
    end

    CaseInsensitiveSchema = Dry::Validation.Schema do
    BRANDS = %w(several hundred valid brands)

    configure do
    def in_brand_list?(value)
    BRANDS.include? value.downcase
    end
    end

    required(:brand).value(:in_brand_list?)
    end


    # A valid string if case insensitive
    valid_product = {brand: 'Valid'}

    CaseSensitiveSchema.call(valid_product).errors
    # => {:brand=>["must be one of: here, are, some, valid, brands"]} # This message will be ridiculous when the full brand list is applied

    CaseInsensitiveSchema.call(valid_product).errors
    # => {} # Good!



    invalid_product = {brand: 'Junk'}

    CaseSensitiveSchema.call(invalid_product).errors
    # => {:brand=>["must be one of: several, hundred, valid, brands"]} # Good... (Except this error message will contain the entire brand list!!!)

    CaseInsensitiveSchema.call(invalid_product).errors
    # => Dry::Validation::MissingMessageError: message for in_brand_list? was not found
    # => from .. /gems/2.5.0/gems/dry-validation-0.12.2/lib/dry/validation/message_compiler.rb:116:in `visit_predicate'









    share|improve this question

























      0












      0








      0








      I'm trying to create a validation for a predetermined list of valid brands as part of an ETL pipeline. My validation requires case insensitivity, as some brands are compound words or abbreviations that are insignificant.



      I created a custom predicate, but I cannot figure out how to generate the appropriate error message.



      I read the error messages doc, but am having a hard time interpreting:




      • How to build the syntax for my custom predicate?

      • Can I apply the messages in my schema class directly, without referencing an external .yml file? I looked here and it seems like it's not as straightforward as I'd hoped.


      Below I've given code that represents what I have tried using both built-in predicates, and a custom one, each with their own issues. If there is a better way to compose a rule that achieves the same goal, I'd love to learn it.



      require 'dry/validation'

      CaseSensitiveSchema = Dry::Validation.Schema do
      BRANDS = %w(several hundred valid brands)

      # :included_in? from https://dry-rb.org/gems/dry-validation/basics/built-in-predicates/
      required(:brand).value(included_in?: BRANDS)
      end

      CaseInsensitiveSchema = Dry::Validation.Schema do
      BRANDS = %w(several hundred valid brands)

      configure do
      def in_brand_list?(value)
      BRANDS.include? value.downcase
      end
      end

      required(:brand).value(:in_brand_list?)
      end


      # A valid string if case insensitive
      valid_product = {brand: 'Valid'}

      CaseSensitiveSchema.call(valid_product).errors
      # => {:brand=>["must be one of: here, are, some, valid, brands"]} # This message will be ridiculous when the full brand list is applied

      CaseInsensitiveSchema.call(valid_product).errors
      # => {} # Good!



      invalid_product = {brand: 'Junk'}

      CaseSensitiveSchema.call(invalid_product).errors
      # => {:brand=>["must be one of: several, hundred, valid, brands"]} # Good... (Except this error message will contain the entire brand list!!!)

      CaseInsensitiveSchema.call(invalid_product).errors
      # => Dry::Validation::MissingMessageError: message for in_brand_list? was not found
      # => from .. /gems/2.5.0/gems/dry-validation-0.12.2/lib/dry/validation/message_compiler.rb:116:in `visit_predicate'









      share|improve this question














      I'm trying to create a validation for a predetermined list of valid brands as part of an ETL pipeline. My validation requires case insensitivity, as some brands are compound words or abbreviations that are insignificant.



      I created a custom predicate, but I cannot figure out how to generate the appropriate error message.



      I read the error messages doc, but am having a hard time interpreting:




      • How to build the syntax for my custom predicate?

      • Can I apply the messages in my schema class directly, without referencing an external .yml file? I looked here and it seems like it's not as straightforward as I'd hoped.


      Below I've given code that represents what I have tried using both built-in predicates, and a custom one, each with their own issues. If there is a better way to compose a rule that achieves the same goal, I'd love to learn it.



      require 'dry/validation'

      CaseSensitiveSchema = Dry::Validation.Schema do
      BRANDS = %w(several hundred valid brands)

      # :included_in? from https://dry-rb.org/gems/dry-validation/basics/built-in-predicates/
      required(:brand).value(included_in?: BRANDS)
      end

      CaseInsensitiveSchema = Dry::Validation.Schema do
      BRANDS = %w(several hundred valid brands)

      configure do
      def in_brand_list?(value)
      BRANDS.include? value.downcase
      end
      end

      required(:brand).value(:in_brand_list?)
      end


      # A valid string if case insensitive
      valid_product = {brand: 'Valid'}

      CaseSensitiveSchema.call(valid_product).errors
      # => {:brand=>["must be one of: here, are, some, valid, brands"]} # This message will be ridiculous when the full brand list is applied

      CaseInsensitiveSchema.call(valid_product).errors
      # => {} # Good!



      invalid_product = {brand: 'Junk'}

      CaseSensitiveSchema.call(invalid_product).errors
      # => {:brand=>["must be one of: several, hundred, valid, brands"]} # Good... (Except this error message will contain the entire brand list!!!)

      CaseInsensitiveSchema.call(invalid_product).errors
      # => Dry::Validation::MissingMessageError: message for in_brand_list? was not found
      # => from .. /gems/2.5.0/gems/dry-validation-0.12.2/lib/dry/validation/message_compiler.rb:116:in `visit_predicate'






      ruby predicate dry-rb






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 19 '18 at 18:18









      Mr. TimMr. Tim

      649514




      649514
























          1 Answer
          1






          active

          oldest

          votes


















          0














          The correct way to reference my error message was to reference the predicate method. No need to worry about arg, value, etc.



          en:
          errors:
          in_brand_list?: "must be in the master brands list"


          Additionally, I was able to load this error message without a separate .yml by doing this:



          CaseInsensitiveSchema = Dry::Validation.Schema do
          BRANDS = %w(several hundred valid brands)

          configure do
          def in_brand_list?(value)
          BRANDS.include? value.downcase
          end

          def self.messages
          super.merge({en: {errors: {in_brand_list?: "must be in the master brand list"}}})
          end
          end

          required(:brand).value(:in_brand_list?)
          end


          I'd still love to see other implementations, specifically for a generic case-insensitive predicate. Many people say dry-rb is fantastically organized, but I find it hard to follow.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53380501%2fdry-validation-case-insensitive-included-in-validation-with-dryvalidation%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            The correct way to reference my error message was to reference the predicate method. No need to worry about arg, value, etc.



            en:
            errors:
            in_brand_list?: "must be in the master brands list"


            Additionally, I was able to load this error message without a separate .yml by doing this:



            CaseInsensitiveSchema = Dry::Validation.Schema do
            BRANDS = %w(several hundred valid brands)

            configure do
            def in_brand_list?(value)
            BRANDS.include? value.downcase
            end

            def self.messages
            super.merge({en: {errors: {in_brand_list?: "must be in the master brand list"}}})
            end
            end

            required(:brand).value(:in_brand_list?)
            end


            I'd still love to see other implementations, specifically for a generic case-insensitive predicate. Many people say dry-rb is fantastically organized, but I find it hard to follow.






            share|improve this answer




























              0














              The correct way to reference my error message was to reference the predicate method. No need to worry about arg, value, etc.



              en:
              errors:
              in_brand_list?: "must be in the master brands list"


              Additionally, I was able to load this error message without a separate .yml by doing this:



              CaseInsensitiveSchema = Dry::Validation.Schema do
              BRANDS = %w(several hundred valid brands)

              configure do
              def in_brand_list?(value)
              BRANDS.include? value.downcase
              end

              def self.messages
              super.merge({en: {errors: {in_brand_list?: "must be in the master brand list"}}})
              end
              end

              required(:brand).value(:in_brand_list?)
              end


              I'd still love to see other implementations, specifically for a generic case-insensitive predicate. Many people say dry-rb is fantastically organized, but I find it hard to follow.






              share|improve this answer


























                0












                0








                0







                The correct way to reference my error message was to reference the predicate method. No need to worry about arg, value, etc.



                en:
                errors:
                in_brand_list?: "must be in the master brands list"


                Additionally, I was able to load this error message without a separate .yml by doing this:



                CaseInsensitiveSchema = Dry::Validation.Schema do
                BRANDS = %w(several hundred valid brands)

                configure do
                def in_brand_list?(value)
                BRANDS.include? value.downcase
                end

                def self.messages
                super.merge({en: {errors: {in_brand_list?: "must be in the master brand list"}}})
                end
                end

                required(:brand).value(:in_brand_list?)
                end


                I'd still love to see other implementations, specifically for a generic case-insensitive predicate. Many people say dry-rb is fantastically organized, but I find it hard to follow.






                share|improve this answer













                The correct way to reference my error message was to reference the predicate method. No need to worry about arg, value, etc.



                en:
                errors:
                in_brand_list?: "must be in the master brands list"


                Additionally, I was able to load this error message without a separate .yml by doing this:



                CaseInsensitiveSchema = Dry::Validation.Schema do
                BRANDS = %w(several hundred valid brands)

                configure do
                def in_brand_list?(value)
                BRANDS.include? value.downcase
                end

                def self.messages
                super.merge({en: {errors: {in_brand_list?: "must be in the master brand list"}}})
                end
                end

                required(:brand).value(:in_brand_list?)
                end


                I'd still love to see other implementations, specifically for a generic case-insensitive predicate. Many people say dry-rb is fantastically organized, but I find it hard to follow.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 19 '18 at 21:50









                Mr. TimMr. Tim

                649514




                649514






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53380501%2fdry-validation-case-insensitive-included-in-validation-with-dryvalidation%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                    ComboBox Display Member on multiple fields

                    Is it possible to collect Nectar points via Trainline?