-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add Primitive::String with with smart detection for ActiveSuppo…
…rt and Dry inflector (And rasoable fallback)
- Loading branch information
Showing
2 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
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 |
This file contains 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
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 |