Skip to content

Commit

Permalink
feat: add Primitive::String with with smart detection for ActiveSuppo…
Browse files Browse the repository at this point in the history
…rt and Dry inflector (And rasoable fallback)
  • Loading branch information
marcosgz committed Jan 23, 2025
1 parent ac9be46 commit e85e651
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 0 deletions.
55 changes: 55 additions & 0 deletions lib/lepus/primitive/string.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

begin
require "dry/inflector"
rescue LoadError
# noop
end

begin
require "active_support/inflector"
rescue LoadError
# noop
end

module Lepus::Primitive
class String < ::String
def classify
new_str = if defined?(Dry::Inflector)
Dry::Inflector.new.classify(self)
elsif defined?(ActiveSupport::Inflector)
ActiveSupport::Inflector.classify(self)
else
split("/").collect do |c|
c.split("_").collect(&:capitalize).join
end.join("::")
end

self.class.new(new_str)
end

def constantize
if defined?(Dry::Inflector)
Dry::Inflector.new.constantize(self)
elsif defined?(ActiveSupport::Inflector)
ActiveSupport::Inflector.constantize(self)
else
Object.const_get(self)
end
end

def underscore
new_str = sub(/^::/, "")
.gsub("::", "/")
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
.tr("-", "_")
.tr(".", "_")
.gsub(/\s/, "_")
.gsub(/__+/, "_")
.downcase

self.class.new(new_str)
end
end
end
129 changes: 129 additions & 0 deletions spec/lepus/primitive/string_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# frozen_string_literal: true

require "spec_helper"

RSpec.describe Lepus::Primitive::String do
describe "#classify" do
context "when dry-inflector is available" do
before do
stub_const("Dry::Inflector", Class.new {
def classify(string)
"Classified"
end
})
end

it "returns the classified string" do
expect(described_class.new("string").classify).to eq("Classified")
end
end

context "when active-support is available" do
before do
stub_const("ActiveSupport::Inflector", Class.new {
def self.classify(string)
"Classified"
end
})
end

it "returns the classified string" do
expect(described_class.new("string").classify).to eq("Classified")
end
end

context "when no inflector is available" do
it "returns the classified string" do
expect(described_class.new("my_string").classify).to eq("MyString")
end
end
end

describe "#constantize" do
let(:constant) { Class.new }

before do
stub_const("MyConstant", constant)
end

context "when dry-inflector is available" do
before do
stub_const("Dry::Inflector", Class.new {
def constantize(string)
MyConstant if string == "MyConstant"
end
})
end

it "returns the constantized string" do
expect(described_class.new("MyConstant").constantize).to eq(constant)
end
end

context "when active-support is available" do
before do
stub_const("ActiveSupport::Inflector", Class.new {
def self.constantize(string)
MyConstant if string == "MyConstant"
end
})
end

it "returns the constantized string" do
expect(described_class.new("MyConstant").constantize).to eq(constant)
end
end
end

describe "#underscore" do
subject { described_class.new(arg).underscore }

context "with capitalized string" do
let(:arg) { "User" }

it { is_expected.to eq("user") }
end

context "with camelized string" do
let(:arg) { "UserName" }

it { is_expected.to eq("user_name") }
end

context "with parameterized string" do
let(:arg) { "foo-bar" }

it { is_expected.to eq("foo_bar") }
end

context "with camelized string under a namespace" do
let(:arg) { "Apiv2::UserName" }

it { is_expected.to eq("apiv2/user_name") }
end

context "with camelized string with a root namespace" do
let(:arg) { "::UserName" }

it { is_expected.to eq("user_name") }
end

context "with a dot in the string" do
let(:arg) { "user.name" }

it { is_expected.to eq("user_name") }
end

context "with a space in the string" do
let(:arg) { "user name" }

it { is_expected.to eq("user_name") }
end

context "with multiple underscores in the string" do
let(:arg) { "user_______name" }

it { is_expected.to eq("user_name") }
end
end
end

0 comments on commit e85e651

Please sign in to comment.