lotus-utils 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.coveralls.yml +2 -0
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/.yardopts +3 -0
- data/Gemfile +8 -2
- data/README.md +35 -3
- data/Rakefile +10 -1
- data/lib/lotus/utils/callbacks.rb +207 -0
- data/lib/lotus/utils/class.rb +59 -0
- data/lib/lotus/utils/class_attribute.rb +94 -0
- data/lib/lotus/utils/hash.rb +43 -0
- data/lib/lotus/utils/io.rb +37 -0
- data/lib/lotus/utils/path_prefix.rb +84 -0
- data/lib/lotus/utils/string.rb +113 -0
- data/lib/lotus/utils/version.rb +1 -1
- data/lib/lotus/utils.rb +2 -2
- data/lotus-utils.gemspec +10 -10
- data/test/callbacks_test.rb +213 -0
- data/test/class_attribute_test.rb +132 -0
- data/test/class_test.rb +47 -0
- data/test/hash_test.rb +35 -0
- data/test/io_test.rb +29 -0
- data/test/path_prefix_test.rb +68 -0
- data/test/string_test.rb +75 -0
- data/test/test_helper.rb +15 -0
- data/test/version_test.rb +7 -0
- metadata +39 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab1fa641a480652c1773fc1808f2f920e10e0ffa
|
4
|
+
data.tar.gz: 6c59b62ec336ef0a4e13c64a0e8f71f45dded958
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7dd6940ce3dbebec5d04ae5f05ecb67e2c41cca40579d09d637f0c5a1c64cad083408bff258ec815cfce93480b17d871662e23bc85ae7b7b88a986e115a36978
|
7
|
+
data.tar.gz: 17686034d0c2003a2e42dc1d386b5cd22dc55ebb45cce29707e4283c47a05036b0aefb13e3ad00a34a43547e0efb9dca2f8369ad716b65d24838efd3e6cbe42d
|
data/.coveralls.yml
ADDED
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in lotus-utils.gemspec
|
4
2
|
gemspec
|
3
|
+
|
4
|
+
unless ENV['TRAVIS']
|
5
|
+
gem 'debugger', require: false, platforms: :ruby
|
6
|
+
gem 'yard', require: false
|
7
|
+
gem 'simplecov', require: false
|
8
|
+
end
|
9
|
+
|
10
|
+
gem 'coveralls', require: false
|
data/README.md
CHANGED
@@ -1,6 +1,26 @@
|
|
1
1
|
# Lotus::Utils
|
2
2
|
|
3
|
-
|
3
|
+
Ruby core extentions and class utilities for [Lotus](http://lotusrb.org)
|
4
|
+
|
5
|
+
## Status
|
6
|
+
|
7
|
+
[](http://badge.fury.io/rb/lotus-utils)
|
8
|
+
[](http://travis-ci.org/lotus/utils?branch=master)
|
9
|
+
[](https://coveralls.io/r/lotus/utils)
|
10
|
+
[](https://codeclimate.com/github/lotus/utils)
|
11
|
+
[](https://gemnasium.com/lotus/utils)
|
12
|
+
|
13
|
+
## Contact
|
14
|
+
|
15
|
+
* Home page: http://lotusrb.org
|
16
|
+
* Mailing List: http://lotusrb.org/mailing-list
|
17
|
+
* API Doc: http://rdoc.info/gems/lotus-utils
|
18
|
+
* Bugs/Issues: https://github.com/lotus/utils/issues
|
19
|
+
* Support: http://stackoverflow.com/questions/tagged/lotusrb
|
20
|
+
|
21
|
+
## Rubies
|
22
|
+
|
23
|
+
__Lotus::Utils__ supports Ruby (MRI) 2+
|
4
24
|
|
5
25
|
## Installation
|
6
26
|
|
@@ -18,12 +38,24 @@ Or install it yourself as:
|
|
18
38
|
|
19
39
|
## Usage
|
20
40
|
|
21
|
-
|
41
|
+
__Lotus::Utils__ is designed to enhance Ruby's code and stdlib.
|
42
|
+
By default this gem doesn't load any code, require yourself what you need.
|
43
|
+
|
44
|
+
Please read the documentation of each module, in order to understand how to use
|
45
|
+
each feature.
|
46
|
+
|
47
|
+
## Versioning
|
48
|
+
|
49
|
+
__Lotus::Utils__ uses [Semantic Versioning 2.0.0](http://semver.org)
|
22
50
|
|
23
51
|
## Contributing
|
24
52
|
|
25
|
-
1. Fork it
|
53
|
+
1. Fork it
|
26
54
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
55
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
56
|
4. Push to the branch (`git push origin my-new-feature`)
|
29
57
|
5. Create new Pull Request
|
58
|
+
|
59
|
+
## Copyright
|
60
|
+
|
61
|
+
Copyright 2014 Luca Guidi – Released under MIT License
|
data/Rakefile
CHANGED
@@ -0,0 +1,207 @@
|
|
1
|
+
module Lotus
|
2
|
+
module Utils
|
3
|
+
# Before and After callbacks
|
4
|
+
#
|
5
|
+
# @since 0.1.0
|
6
|
+
# @private
|
7
|
+
module Callbacks
|
8
|
+
# Series of callbacks to be executed
|
9
|
+
#
|
10
|
+
# @since 0.1.0
|
11
|
+
# @private
|
12
|
+
class Chain < ::Array
|
13
|
+
# Adds the given callbacks to the chain
|
14
|
+
#
|
15
|
+
# @param callbacks [Array] one or multiple callbacks to add
|
16
|
+
# @param blk [Proc] an optional block to be added
|
17
|
+
#
|
18
|
+
# @return [void]
|
19
|
+
#
|
20
|
+
# @see #run
|
21
|
+
# @see Lotus::Utils::Callbacks::Callback
|
22
|
+
# @see Lotus::Utils::Callbacks::MethodCallback
|
23
|
+
#
|
24
|
+
# @since 0.1.0
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# require 'lotus/utils/callbacks'
|
28
|
+
#
|
29
|
+
# chain = Lotus::Utils::Callbacks::Chain.new
|
30
|
+
#
|
31
|
+
# # Add a Proc to be used as a callback, it will be wrapped by `Callback`
|
32
|
+
# # The optional argument(s) correspond to the one passed when invoked the chain with `run`.
|
33
|
+
# chain.add { Authenticator.authenticate! }
|
34
|
+
# chain.add {|params| ArticleRepository.find(params[:id]) }
|
35
|
+
#
|
36
|
+
# # Add a Symbol as a reference to a method name that will be used as a callback.
|
37
|
+
# # It will wrapped by `MethodCallback`
|
38
|
+
# # If the #notificate method accepts some argument(s) they should be passed when `run` is invoked.
|
39
|
+
# chain.add :notificate
|
40
|
+
def add(*callbacks, &blk)
|
41
|
+
callbacks.push blk if block_given?
|
42
|
+
callbacks.each do |c|
|
43
|
+
push Factory.fabricate(c)
|
44
|
+
end
|
45
|
+
|
46
|
+
uniq!
|
47
|
+
end
|
48
|
+
|
49
|
+
# Runs all the callbacks in the chain.
|
50
|
+
# The only two ways to stop the execution are: `raise` or `throw`.
|
51
|
+
#
|
52
|
+
# @param context [Object] the context where we want the chain to be invoked.
|
53
|
+
# @param args [Array] the arguments that we want to pass to each single callback.
|
54
|
+
#
|
55
|
+
# @since 0.1.0
|
56
|
+
#
|
57
|
+
# @example
|
58
|
+
# require 'lotus/utils/callbacks'
|
59
|
+
#
|
60
|
+
# class Action
|
61
|
+
# private
|
62
|
+
# def authenticate!
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# def set_article(params)
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# action = Action.new
|
70
|
+
# params = Hash[id: 23]
|
71
|
+
#
|
72
|
+
# chain = Lotus::Utils::Callbacks::Chain.new
|
73
|
+
# chain.add :authenticate!, :set_article
|
74
|
+
#
|
75
|
+
# chain.run(action, params)
|
76
|
+
#
|
77
|
+
# # `params` will only be passed as #set_article argument, because it has an arity greater than zero
|
78
|
+
#
|
79
|
+
#
|
80
|
+
#
|
81
|
+
# chain = Lotus::Utils::Callbacks::Chain.new
|
82
|
+
#
|
83
|
+
# chain.add do
|
84
|
+
# # some authentication logic
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# chain.add do |params|
|
88
|
+
# # some other logic that requires `params`
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# chain.run(action, params)
|
92
|
+
#
|
93
|
+
# Those callbacks will be invoked within the context of `action`.
|
94
|
+
def run(context, *args)
|
95
|
+
each do |callback|
|
96
|
+
callback.call(context, *args)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Callback factory
|
102
|
+
#
|
103
|
+
# @since 0.1.0
|
104
|
+
# @private
|
105
|
+
class Factory
|
106
|
+
# Instantiates a `Callback` according to if it responds to #call.
|
107
|
+
#
|
108
|
+
# @param callback [Object] the object that needs to be wrapped
|
109
|
+
#
|
110
|
+
# @return [Callback, MethodCallback]
|
111
|
+
#
|
112
|
+
# @since 0.1.0
|
113
|
+
#
|
114
|
+
# @example
|
115
|
+
# require 'lotus/utils/callbacks'
|
116
|
+
#
|
117
|
+
# callable = Proc.new{} # it responds to #call
|
118
|
+
# method = :upcase # it doesn't responds to #call
|
119
|
+
#
|
120
|
+
# Lotus::Utils::Callbacks::Factory.fabricate(callable).class
|
121
|
+
# # => Lotus::Utils::Callbacks::Callback
|
122
|
+
#
|
123
|
+
# Lotus::Utils::Callbacks::Factory.fabricate(method).class
|
124
|
+
# # => Lotus::Utils::Callbacks::MethodCallback
|
125
|
+
def self.fabricate(callback)
|
126
|
+
if callback.respond_to?(:call)
|
127
|
+
Callback.new(callback)
|
128
|
+
else
|
129
|
+
MethodCallback.new(callback)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Proc callback
|
135
|
+
# It wraps an object that responds to #call
|
136
|
+
#
|
137
|
+
# @since 0.1.0
|
138
|
+
# @private
|
139
|
+
class Callback
|
140
|
+
attr_reader :callback
|
141
|
+
|
142
|
+
# Initialize by wrapping the given callback
|
143
|
+
#
|
144
|
+
# @param callback [Object] the original callback that needs to be wrapped
|
145
|
+
#
|
146
|
+
# @return [Callback] self
|
147
|
+
#
|
148
|
+
# @since 0.1.0
|
149
|
+
#
|
150
|
+
def initialize(callback)
|
151
|
+
@callback = callback
|
152
|
+
end
|
153
|
+
|
154
|
+
# Executes the callback within the given context and passing the given arguments.
|
155
|
+
#
|
156
|
+
# @param context [Object] the context within we want to execute the callback.
|
157
|
+
# @param args [Array] an array of arguments that will be available within the execution.
|
158
|
+
#
|
159
|
+
# @return [void, Object] It may return a value, it depends on the callback.
|
160
|
+
#
|
161
|
+
# @since 0.1.0
|
162
|
+
#
|
163
|
+
# @see Lotus::Utils::Callbacks::Chain#run
|
164
|
+
def call(context, *args)
|
165
|
+
context.instance_exec(*args, &callback)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Method callback
|
170
|
+
# It wraps a symbol or a string representing a method name that is implemented by the context within it will be called.
|
171
|
+
#
|
172
|
+
# @since 0.1.0
|
173
|
+
# @private
|
174
|
+
class MethodCallback < Callback
|
175
|
+
# Executes the callback within the given context and eventually passing the given arguments.
|
176
|
+
# Those arguments will be passed according to the arity of the target method.
|
177
|
+
#
|
178
|
+
# @param context [Object] the context within we want to execute the callback.
|
179
|
+
# @param args [Array] an array of arguments that will be available within the execution.
|
180
|
+
#
|
181
|
+
# @return [void, Object] It may return a value, it depends on the callback.
|
182
|
+
#
|
183
|
+
# @since 0.1.0
|
184
|
+
#
|
185
|
+
# @see Lotus::Utils::Callbacks::Chain#run
|
186
|
+
def call(context, *args)
|
187
|
+
method = context.method(callback)
|
188
|
+
|
189
|
+
if method.parameters.any?
|
190
|
+
method.call(*args)
|
191
|
+
else
|
192
|
+
method.call
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
protected
|
197
|
+
def hash
|
198
|
+
callback.hash
|
199
|
+
end
|
200
|
+
|
201
|
+
def eql?(other)
|
202
|
+
hash == other.hash
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'lotus/utils/string'
|
2
|
+
|
3
|
+
module Lotus
|
4
|
+
module Utils
|
5
|
+
# Class utilities
|
6
|
+
# @since 0.1.0
|
7
|
+
class Class
|
8
|
+
# Loads a class for the given string or pattern.
|
9
|
+
#
|
10
|
+
# @param name [String] the specific class name or pattern for the class that we want to load
|
11
|
+
#
|
12
|
+
# @param namespace [Class, Module] the Ruby namespace where we want to perform the lookup.
|
13
|
+
#
|
14
|
+
# @return [Class, Module] the found Ruby constant.
|
15
|
+
#
|
16
|
+
# @raise [NameError] if no constant can be found.
|
17
|
+
#
|
18
|
+
# @since 0.1.0
|
19
|
+
#
|
20
|
+
# @see Lotus::Utils::String#tokenize
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# require 'lotus/utils/class'
|
24
|
+
#
|
25
|
+
# module App
|
26
|
+
# module Service
|
27
|
+
# class Endpoint
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# class ServiceEndpoint
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # basic usage
|
36
|
+
# Lotus::Utils::Class.load!('App::Service') # => App::Service
|
37
|
+
#
|
38
|
+
# # with explicit namespace
|
39
|
+
# Lotus::Utils::Class.load!('Service', App) # => App::Service
|
40
|
+
#
|
41
|
+
# # with pattern
|
42
|
+
# Lotus::Utils::Class.load!('App::Service(::Endpoint|Endpoint)') # => App::Service::Endpoint
|
43
|
+
# Lotus::Utils::Class.load!('App::Service(Endpoint|::Endpoint)') # => App::ServiceEndpoint
|
44
|
+
#
|
45
|
+
# # with missing constant
|
46
|
+
# Lotus::Utils::Class.load!('Unknown') # => raises NameError
|
47
|
+
def self.load!(name, namespace = Object)
|
48
|
+
String.new(name).tokenize do |token|
|
49
|
+
begin
|
50
|
+
return namespace.const_get(token)
|
51
|
+
rescue NameError
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
raise NameError.new(name)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Lotus
|
2
|
+
module Utils
|
3
|
+
# Inheritable class level variable accessors.
|
4
|
+
# @since 0.1.0
|
5
|
+
#
|
6
|
+
# @see Lotus::Utils::ClassAttribute::ClassMethods
|
7
|
+
module ClassAttribute
|
8
|
+
def self.included(base)
|
9
|
+
base.class_eval do
|
10
|
+
extend ClassMethods
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
# Defines a class level accessor for the given attribute(s).
|
16
|
+
#
|
17
|
+
# A value set for a superclass is automatically available by their
|
18
|
+
# subclasses, unless a different value is explicitely set within the
|
19
|
+
# inheritance chain.
|
20
|
+
#
|
21
|
+
# @param attributes [Array<Symbol>] a single or multiple attribute name(s)
|
22
|
+
#
|
23
|
+
# @return [void]
|
24
|
+
#
|
25
|
+
# @since 0.1.0
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# require 'lotus/utils/class_attribute'
|
29
|
+
#
|
30
|
+
# class Vehicle
|
31
|
+
# include Lotus::Utils::ClassAttribute
|
32
|
+
# class_attribute :engines, :wheels
|
33
|
+
#
|
34
|
+
# self.engines = 0
|
35
|
+
# self.wheels = 0
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# class Car < Vehicle
|
39
|
+
# self.engines = 1
|
40
|
+
# self.wheels = 4
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# class Airplane < Vehicle
|
44
|
+
# self.engines = 4
|
45
|
+
# self.wheels = 16
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# class SmallAirplane < Airplane
|
49
|
+
# self.engines = 2
|
50
|
+
# self.wheels = 8
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# Vehicle.engines # => 0
|
54
|
+
# Vehicle.wheels # => 0
|
55
|
+
#
|
56
|
+
# Car.engines # => 1
|
57
|
+
# Car.wheels # => 4
|
58
|
+
#
|
59
|
+
# Airplane.engines # => 4
|
60
|
+
# Airplane.wheels # => 16
|
61
|
+
#
|
62
|
+
# SmallAirplane.engines # => 2
|
63
|
+
# SmallAirplane.wheels # => 8
|
64
|
+
def class_attribute(*attributes)
|
65
|
+
(class << self; self; end).class_eval do
|
66
|
+
attr_accessor *attributes
|
67
|
+
end
|
68
|
+
|
69
|
+
class_attributes.merge(attributes)
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
# @see Class#inherited
|
74
|
+
def inherited(subclass)
|
75
|
+
class_attributes.each do |attr|
|
76
|
+
value = send(attr)
|
77
|
+
value = value.dup rescue value
|
78
|
+
subclass.class_attribute attr
|
79
|
+
subclass.send("#{attr}=", value)
|
80
|
+
end
|
81
|
+
|
82
|
+
super
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
# Class accessor for class attributes.
|
87
|
+
# @private
|
88
|
+
def class_attributes
|
89
|
+
@class_attributes ||= Set.new
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Lotus
|
2
|
+
module Utils
|
3
|
+
# Hash on steroids
|
4
|
+
# @since 0.1.0
|
5
|
+
class Hash < ::Hash
|
6
|
+
# Initialize the hash
|
7
|
+
#
|
8
|
+
# @param hash [::Hash, Hash] the value we want to use to initialize this instance
|
9
|
+
#
|
10
|
+
# @return [Hash] self
|
11
|
+
#
|
12
|
+
# @since 0.1.0
|
13
|
+
def initialize(hash = {})
|
14
|
+
merge! hash
|
15
|
+
end
|
16
|
+
|
17
|
+
# Convert in-place all the keys to Symbol instances, nested hashes are converted too.
|
18
|
+
#
|
19
|
+
# @return [Hash] self
|
20
|
+
#
|
21
|
+
# @since 0.1.0
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# require 'lotus/utils/hash'
|
25
|
+
#
|
26
|
+
# hash = Lotus::Utils::Hash.new 'a' => 23, 'b' => { 'c' => ['x','y','z'] }
|
27
|
+
# hash.symbolize!
|
28
|
+
#
|
29
|
+
# hash.keys # => [:a, :b]
|
30
|
+
# hash.inspect # => {:a=>23, :b=>{:c=>["x", "y", "z"]}}
|
31
|
+
def symbolize!
|
32
|
+
keys.each do |k|
|
33
|
+
v = delete(k)
|
34
|
+
v = Hash.new(v).symbolize! if v.is_a?(::Hash)
|
35
|
+
|
36
|
+
self[k.to_sym] = v
|
37
|
+
end
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Lotus
|
2
|
+
module Utils
|
3
|
+
# IO utils
|
4
|
+
#
|
5
|
+
# @since 0.1.0
|
6
|
+
class IO
|
7
|
+
# Decreases the level of verbosity, during the execution of the given block.
|
8
|
+
#
|
9
|
+
# Revised version of ActiveSupport's `Kernel.with_warnings` implementation
|
10
|
+
# @see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/kernel/reporting.rb#L25
|
11
|
+
#
|
12
|
+
# @param blk [Proc] the block of code that generates warnings.
|
13
|
+
#
|
14
|
+
# @return [void]
|
15
|
+
#
|
16
|
+
# @since 0.1.0
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# require 'lotus/utils/io'
|
20
|
+
#
|
21
|
+
# class Test
|
22
|
+
# TEST_VALUE = 'initial'
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Lotus::Utils::IO.silence_warnings do
|
26
|
+
# Test::TEST_VALUE = 'redefined'
|
27
|
+
# end
|
28
|
+
def self.silence_warnings(&blk)
|
29
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
30
|
+
blk.call
|
31
|
+
ensure
|
32
|
+
$VERBOSE = old_verbose
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Lotus
|
2
|
+
module Utils
|
3
|
+
# Prefixed string
|
4
|
+
#
|
5
|
+
# @since 0.1.0
|
6
|
+
class PathPrefix < ::String
|
7
|
+
# Initialize the path prefix
|
8
|
+
#
|
9
|
+
# @param string [::String] the prefix value
|
10
|
+
# @param separator [::String] the separator used between tokens
|
11
|
+
#
|
12
|
+
# @return [PathPrefix] self
|
13
|
+
#
|
14
|
+
# @since 0.1.0
|
15
|
+
def initialize(string = nil, separator = '/')
|
16
|
+
@separator = separator
|
17
|
+
super(string.to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Joins self with the given token.
|
21
|
+
# It cleanups the all the `separator` repetitions.
|
22
|
+
#
|
23
|
+
# @param string [::String] the token we want to join
|
24
|
+
#
|
25
|
+
# @return [::String] the joined string
|
26
|
+
#
|
27
|
+
# @since 0.1.0
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# require 'lotus/utils/path_prefix'
|
31
|
+
#
|
32
|
+
# path_prefix = Lotus::Utils::PathPrefix.new '/posts'
|
33
|
+
# path_prefix.join 'new' # => '/posts/new'
|
34
|
+
# path_prefix.join '/new' # => '/posts/new'
|
35
|
+
#
|
36
|
+
# path_prefix = Lotus::Utils::PathPrefix.new 'posts'
|
37
|
+
# path_prefix.join 'new' # => '/posts/new'
|
38
|
+
# path_prefix.join '/new' # => '/posts/new'
|
39
|
+
def join(string)
|
40
|
+
absolutize relative_join(string)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Joins self with the given token, without prefixing it with `separator`.
|
44
|
+
# It cleanups the all the `separator` repetitions.
|
45
|
+
#
|
46
|
+
# @param string [::String] the token we want to join
|
47
|
+
# @param separator [::String] the separator used between tokens
|
48
|
+
#
|
49
|
+
# @return [::String] the joined string
|
50
|
+
#
|
51
|
+
# @since 0.1.0
|
52
|
+
#
|
53
|
+
# @example
|
54
|
+
# require 'lotus/utils/path_prefix'
|
55
|
+
#
|
56
|
+
# path_prefix = Lotus::Utils::PathPrefix.new 'posts'
|
57
|
+
# path_prefix.relative_join 'new' # => 'posts/new'
|
58
|
+
# path_prefix.relative_join 'new', '_' # => 'posts_new'
|
59
|
+
def relative_join(string, separator = @separator)
|
60
|
+
separator = separator || @separator
|
61
|
+
relativize [self, string].join(separator), separator
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
attr_reader :separator
|
66
|
+
|
67
|
+
def absolutize(string)
|
68
|
+
string.tap do |s|
|
69
|
+
s.insert(0, separator) unless absolute?(s)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def absolute?(string)
|
74
|
+
string.start_with?(separator)
|
75
|
+
end
|
76
|
+
|
77
|
+
def relativize(string, separator = @separator)
|
78
|
+
string.
|
79
|
+
gsub(%r{(?<!:)#{ separator * 2 }}, separator).
|
80
|
+
gsub(%r{\A#{ separator }}, '')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|