Skip to content

Commit

Permalink
chore: refactoring primitive string
Browse files Browse the repository at this point in the history
  • Loading branch information
marcosgz committed Feb 3, 2025
1 parent 98f593c commit ae2009f
Show file tree
Hide file tree
Showing 2 changed files with 248 additions and 50 deletions.
85 changes: 68 additions & 17 deletions lib/site_maps/primitive/string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,30 @@

module SiteMaps::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("::")
def self.inflector
return @inflector if defined?(@inflector)

@inflector = if defined?(::ActiveSupport::Inflector)
::ActiveSupport::Inflector
elsif defined?(::Dry::Inflector)
::Dry::Inflector.new
end
end

def classify
new_str = inflector&.classify(self) || split("/").collect do |c|
c.split("_").collect(&:capitalize).join
end.join("::")

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
inflector&.constantize(self) || Object.const_get(self)
end

def underscore
new_str = sub(/^::/, "")
new_str = inflector&.underscore(self) || sub(/^::/, "")
.gsub("::", "/")
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
Expand All @@ -51,5 +49,58 @@ def underscore

self.class.new(new_str)
end

def pluralize
new_str = inflector&.pluralize(self) || begin
# dummy pluralize
if /y$/.match?(self)
sub(/y$/, "ies")
elsif /s$/.match?(self)
self
else
self + "s"
end
end

new_str.is_a?(self.class) ? new_str : self.class.new(new_str)
end

def singularize
new_str = inflector&.singularize(self) || begin
# dummy singularize
if /ies$/.match?(self)
sub(/ies$/, "y")
elsif /s$/.match?(self)
sub(/s$/, "")
else
self
end
end

new_str.is_a?(self.class) ? new_str : self.class.new(new_str)
end

def camelize(uppercase_first_letter = true)
new_str = inflector&.camelize(self, uppercase_first_letter) || begin
# dummy camelize
str = self.to_s
str = str.sub(/^[a-z\d]*/) { $&.capitalize }
str = str.tr("-", "_")
str = str.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
str = str.gsub("/", "::")
unless uppercase_first_letter
str = str.sub(/^[A-Z]*/) { $&.downcase }
end
str
end

self.class.new(new_str)
end

protected

def inflector
self.class.inflector
end
end
end
213 changes: 180 additions & 33 deletions spec/site_maps/primitive/string_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,60 @@
require "spec_helper"

RSpec.describe SiteMaps::Primitive::String do
describe "#classify" do
context "when dry-inflector is available" do
after do
described_class.remove_instance_variable(:@inflector)
end

describe ".inflector" do
subject { described_class.inflector }

before do
described_class.remove_instance_variable(:@inflector)
rescue NameError
end

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

it "returns the classified string" do
expect(described_class.new("string").classify).to eq("Classified")
end
it { is_expected.to eq(ActiveSupport::Inflector) }
end

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

it { is_expected.to be_a(Dry::Inflector) }
end

context "when no inflector is available" do
it { is_expected.to be_nil }
end
end

describe "#classify" do
let(:inflector) { nil }

before do
described_class.instance_variable_set(:@inflector, inflector)
end

context "when inflector is available" do
let(:inflector) do
Class.new {
def classify(string)
"Classified"
end
}.new
end

it "returns the classified string" do
expect(described_class.new("string").classify).to eq("Classified")
allow(inflector).to receive(:classify)
expect(described_class.new("classified").classify).to eq("Classified")

expect(inflector).to have_received(:classify).with("classified")
end
end

Expand All @@ -41,34 +69,28 @@ def self.classify(string)

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

before do
described_class.instance_variable_set(:@inflector, inflector)
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
})
context "when inflector is available" do
let(:inflector) do
Class.new {
def constantize(string)
MyConstant if string == "MyConstant"
end
}.new
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

context "when no inflector is available" do
it "returns the constantized string" do
expect(described_class.new("MyConstant").constantize).to eq(constant)
end
Expand Down Expand Up @@ -126,4 +148,129 @@ def self.constantize(string)
it { is_expected.to eq("user_name") }
end
end

describe "#pluralize" do
let(:inflector) { nil }

before do
described_class.instance_variable_set(:@inflector, inflector)
end

context "when inflector is available" do
let(:inflector) do
Class.new {
def pluralize(string)
"users"
end
}.new
end

it "returns the pluralized string" do
allow(inflector).to receive(:pluralize)
expect(described_class.new("user").pluralize).to eq("users")

expect(inflector).to have_received(:pluralize).with("user")
end
end

context "when no inflector is available" do
it "returns the pluralized string" do
expect(described_class.new("user").pluralize).to eq("users")
end

it "returns pluralized string ending with 'y'" do
expect(described_class.new("city").pluralize).to eq("cities")
end
end
end

describe "#singularize" do
let(:inflector) { nil }

before do
described_class.instance_variable_set(:@inflector, inflector)
end

context "when inflector is available" do
let(:inflector) do
Class.new {
def singularize(string)
"user"
end
}.new
end

it "returns the singularized string" do
allow(inflector).to receive(:singularize)
expect(described_class.new("users").singularize).to eq("user")

expect(inflector).to have_received(:singularize).with("users")
end
end

context "when no inflector is available" do
it "returns the singularized string" do
expect(described_class.new("users").singularize).to eq("user")
end

it "returns singularized string ending with 'ies'" do
expect(described_class.new("cities").singularize).to eq("city")
end
end
end

describe "#camelize" do
let(:inflector) { nil }

before do
described_class.instance_variable_set(:@inflector, inflector)
end

context "when inflector is available" do
let(:inflector) do
Class.new {
def camelize(string, uppercase_first_letter)
"User"
end
}.new
end

it "returns the camelized string" do
allow(inflector).to receive(:camelize)
expect(described_class.new("user").camelize).to eq("User")

expect(inflector).to have_received(:camelize).with("user", true)
end
end

context "when no inflector is available" do
it "returns the camelized string" do
expect(described_class.new("user").camelize).to eq("User")
end

it "returns the camelized string with uppercase first letter" do
expect(described_class.new("user").camelize(true)).to eq("User")
end

it "returns the camelized string with lowercase first letter" do
expect(described_class.new("user").camelize(false)).to eq("user")
end

it "returns the camelized string with uppercase first letter and underscore" do
expect(described_class.new("user_name").camelize(true)).to eq("UserName")
end

it "returns the camelized string with lowercase first letter and underscore" do
expect(described_class.new("user_name").camelize(false)).to eq("userName")
end

it "returns the camelized string with uppercase first letter and dash" do
expect(described_class.new("user-name").camelize(true)).to eq("UserName")
end

it "returns the camelized string with namespace" do
expect(described_class.new("admin/user_name").camelize(true)).to eq("Admin::UserName")
end
end
end
end

0 comments on commit ae2009f

Please sign in to comment.