From b7c79e8f54ca5e42937452ea1cf48ae1cc9329c9 Mon Sep 17 00:00:00 2001 From: Henk <henk.van.der.veen@gmail.com> Date: Tue, 30 Mar 2021 23:51:15 +0200 Subject: [PATCH] add stripped_string type --- README.md | 23 +++++++++++++++++ lib/roqua/type.rb | 7 +++++ lib/roqua/type/stripped_string.rb | 34 +++++++++++++++++++++++++ spec/roqua/type/stripped_string_spec.rb | 34 +++++++++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 lib/roqua/type.rb create mode 100644 lib/roqua/type/stripped_string.rb create mode 100644 spec/roqua/type/stripped_string_spec.rb diff --git a/README.md b/README.md index 4d640f7..f4e3e0c 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,29 @@ class ApiAreaController < ApplicationController ... ``` +### Types + +In initializer: + +```ruby +require 'roqua/type' +``` + +In models: + +```ruby +# strip whitespace and nil if blank. +attribute :firstname, :stripped_string +# strip, but don't nil if blank. +attribute :firstname, :stripped_string, allow_empty: true +``` + +#### option 2 + +`require 'roqua/type/stripped_string'` + +`attribute :firstname, Roqua::Type::StrippedString.new(allow_empty: true)` + # Delayed Job activity monitoring To add monitoring of whether Delayed Job keeps picking up jobs or checking for new jobs, add the following line to an initializer: diff --git a/lib/roqua/type.rb b/lib/roqua/type.rb new file mode 100644 index 0000000..f2407de --- /dev/null +++ b/lib/roqua/type.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require "active_model/type" + +require_relative "./type/stripped_string" + +ActiveRecord::Type.register(:stripped_string, Roqua::Type::StrippedString) diff --git a/lib/roqua/type/stripped_string.rb b/lib/roqua/type/stripped_string.rb new file mode 100644 index 0000000..ef072a9 --- /dev/null +++ b/lib/roqua/type/stripped_string.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +# Strips whitespace and make nil when string becomes empty. +module Roqua + module Type + class StrippedString < ActiveModel::Type::ImmutableString + # taken from strip_attributes gem + # Unicode invisible and whitespace characters. The POSIX character class + # [:space:] corresponds to the Unicode class Z ("separator"). We also + # include the following characters from Unicode class C ("control"), which + # are spaces or invisible characters that make no sense at the start or end + # of a string: + # U+180E MONGOLIAN VOWEL SEPARATOR + # U+200B ZERO WIDTH SPACE + # U+200C ZERO WIDTH NON-JOINER + # U+200D ZERO WIDTH JOINER + # U+2060 WORD JOINER + # U+FEFF ZERO WIDTH NO-BREAK SPACE + MULTIBYTE_WHITE = "\u180E\u200B\u200C\u200D\u2060\uFEFF" + MULTIBYTE_SPACE = /[[:space:]#{MULTIBYTE_WHITE}]/.freeze + + def initialize(allow_empty: false) + super() + @allow_empty = allow_empty + end + + def cast(value) + return unless value + value = super(value).gsub(/\A#{MULTIBYTE_SPACE}+|#{MULTIBYTE_SPACE}+\z/, "").freeze + value.blank? && !@allow_empty ? nil : value + end + end + end +end diff --git a/spec/roqua/type/stripped_string_spec.rb b/spec/roqua/type/stripped_string_spec.rb new file mode 100644 index 0000000..2f5bf53 --- /dev/null +++ b/spec/roqua/type/stripped_string_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'roqua/type/stripped_string' + +RSpec.describe Roqua::Type::StrippedString do + let(:cls) do + Class.new(ActiveRecord::Base) do + self.table_name = 'delayed_jobs' + + attribute :locked_by, Roqua::Type::StrippedString.new + attribute :queue, Roqua::Type::StrippedString.new(allow_empty: true) + end + end + + it "strips whitespace from outside and not inside" do + expect(described_class.new.cast(" some name \n \t \u180E\u200B\u200C\u200D\u2060\uFEFF ")).to eq "some name" + end + + it "nils empty values by default" do + expect(described_class.new.cast(" \n \t ")).to eq nil + end + + it "keeps value empty if allow_empty is true" do + expect(described_class.new(allow_empty: true).cast(" \n \t ")).to eq "" + end + + it "works on active_record" do + instance = cls.new(locked_by: " \n \t ", queue: " \n \t ", cron: " \n \t ") + expect(instance.locked_by).to be_nil + expect(instance.queue).to eq "" + expect(instance.cron).to eq " \n \t " + end +end -- GitLab