hanami-utils 0.8.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0ec07bde18ad072abdc5ba80712ccf9976d4139
4
- data.tar.gz: 98916abdaf10d4a18848745fe00ba6b497a3e521
3
+ metadata.gz: 93e8362df57ad7209539ecd8383ee1f1b60ea68e
4
+ data.tar.gz: 854db004fcc6912bef61404d58feda11e6589d2e
5
5
  SHA512:
6
- metadata.gz: 459b2bcf58fd4416d95421ed9d0af9995096caef9a32975a51ca69ebd771a8ba4352935f76f26702a1c248a7af256c01e0683101410800f02808761da548eaf7
7
- data.tar.gz: 475a12099d5f21b95ccc7965571351e98f8b6eb55a46343952483eac7fdb3cb3f51daaa6818b99c5e991696caeda3a2bcb3910c078deb64e14a82e91f7612f0c
6
+ metadata.gz: f30cb4ccc8c96a99808534957ec785f8036cd1baf9362bca8e9f8f15cfad044406c5bb34820b6c6b64faf4cc20e3cbd6ef36e08193754adf2c6980ef9a6f5862
7
+ data.tar.gz: 734d3c0994e2ccba6e9176c497c17c8093693da2b434dbd2476383128a57f83819c7f63382ba39a22057cbd6b72361dd6ec9e51a4989d0c5d070d3c2837f7b1c
@@ -1,6 +1,20 @@
1
1
  # Hanami::Utils
2
2
  Ruby core extentions and class utilities for Hanami
3
3
 
4
+ ## v0.9.0 - 2016-11-15
5
+ ### Added
6
+ – [Luca Guidi] Introduced `Utils.require!` to recursively require Ruby files with an order that is consistent across platforms
7
+ – [Luca Guidi] Introduced `Utils::FileList` as cross-platform ordered list of files, alternative to `Dir.glob`
8
+ - [Luca Guidi] Make `Utils::BasicObject` pretty printable
9
+ - [Grachev Mikhail] Added `Interactor::Result#successful?` and `#failing?`
10
+
11
+ ### Fixed
12
+ - [Pascal Betz] Ensure `Utils::Class.load!` to lookup constant only within the given namespace
13
+
14
+ ### Changed
15
+ - [Luca Guidi] Make `Utils::Hash` only compatible with objects that respond to `#to_hash`
16
+ - [Luca Guidi] Official support for Ruby: MRI 2.3+ and JRuby 9.1.5.0+
17
+
4
18
  ## v0.8.0 - 2016-07-22
5
19
  ### Added
6
20
  - [Andrey Morskov] Introduced `Hanami::Utils::Blank`
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Hanami::Utils
2
2
 
3
- Ruby core extentions and class utilities for [Hanami](http://hanamirb.org)
3
+ Ruby core extensions and class utilities for [Hanami](http://hanamirb.org)
4
4
 
5
5
  ## Status
6
6
 
@@ -22,7 +22,7 @@ Ruby core extentions and class utilities for [Hanami](http://hanamirb.org)
22
22
 
23
23
  ## Rubies
24
24
 
25
- __Hanami::Utils__ supports Ruby (MRI) 2.2+, JRuby 9.0.5.0+
25
+ __Hanami::Utils__ supports Ruby (MRI) 2.3+, JRuby 9.1.5.0+
26
26
 
27
27
  ## Installation
28
28
 
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
- spec.required_ruby_version = '>= 2.2.0'
20
+ spec.required_ruby_version = '>= 2.3.0'
21
21
 
22
22
  spec.add_development_dependency 'bundler', '~> 1.6'
23
23
  spec.add_development_dependency 'rake', '~> 11'
@@ -17,7 +17,14 @@ module Hanami
17
17
  # @api private
18
18
  #
19
19
  # @see Hanami::Interactor::Result#respond_to_missing?
20
- METHODS = ::Hash[initialize: true, success?: true, fail!: true, prepare!: true, errors: true, error: true].freeze
20
+ METHODS = ::Hash[initialize: true,
21
+ success?: true,
22
+ successful?: true,
23
+ failing?: true,
24
+ fail!: true,
25
+ prepare!: true,
26
+ errors: true,
27
+ error: true].freeze
21
28
 
22
29
  # Initialize a new result
23
30
  #
@@ -37,11 +44,23 @@ module Hanami
37
44
  #
38
45
  # @return [TrueClass,FalseClass] the result of the check
39
46
  #
40
- # @since 0.3.5
41
- def success?
47
+ # @since 0.8.1
48
+ def successful?
42
49
  @success && errors.empty?
43
50
  end
44
51
 
52
+ # @since 0.3.5
53
+ alias success? successful?
54
+
55
+ # Check if the current status is not successful
56
+ #
57
+ # @return [TrueClass,FalseClass] the result of the check
58
+ #
59
+ # @since 0.8.1
60
+ def failing?
61
+ !successful?
62
+ end
63
+
45
64
  # Force the status to be a failure
46
65
  #
47
66
  # @since 0.3.5
@@ -202,7 +221,8 @@ module Hanami
202
221
  # end
203
222
  #
204
223
  # result = Signup.new(name: 'Luca').call
205
- # result.success? # => true
224
+ # result.failing? # => false
225
+ # result.successful? # => true
206
226
  #
207
227
  # result.user # => #<User:0x007fa311105778 @id=1 @name="Luca">
208
228
  # result.params # => { :name=>"Luca" }
@@ -232,7 +252,8 @@ module Hanami
232
252
  # end
233
253
  #
234
254
  # result = Signup.new(name: nil).call
235
- # result.success? # => false
255
+ # result.successful? # => false
256
+ # result.failing? # => true
236
257
  #
237
258
  # result.user # => #<User:0x007fa311105778 @id=nil @name="Luca">
238
259
  #
@@ -299,7 +320,7 @@ module Hanami
299
320
  # end
300
321
  #
301
322
  # result = CreateEmailTest.new(account_id: 1).call
302
- # result.success? # => false
323
+ # result.successful? # => false
303
324
  def fail!
304
325
  @__result.fail!
305
326
  throw :fail
@@ -351,7 +372,7 @@ module Hanami
351
372
  # end
352
373
  #
353
374
  # result = CreateRecord.new.call
354
- # result.success? # => false
375
+ # result.successful? # => false
355
376
  #
356
377
  # result.errors # => ["Prepare data error", "Persist error"]
357
378
  # result.logger # => [:prepare_data!, :persist!, :sync!]
@@ -405,7 +426,7 @@ module Hanami
405
426
  # end
406
427
  #
407
428
  # result = CreateRecord.new.call
408
- # result.success? # => false
429
+ # result.successful? # => false
409
430
  #
410
431
  # result.errors # => ["Prepare data error", "Persist error"]
411
432
  # result.logger # => [:prepare_data!, :persist!]
@@ -1,6 +1,10 @@
1
- require 'hanami/utils/version'
2
-
1
+ # Hanami - The web, with simplicity
2
+ #
3
+ # @since 0.1.0
3
4
  module Hanami
5
+ require 'hanami/utils/version'
6
+ require 'hanami/utils/file_list'
7
+
4
8
  # Ruby core extentions and Hanami utilities
5
9
  #
6
10
  # @since 0.1.0
@@ -32,5 +36,24 @@ module Hanami
32
36
  def self.rubinius?
33
37
  RUBY_ENGINE == HANAMI_RUBINIUS
34
38
  end
39
+
40
+ # Recursively require Ruby files under the given directory.
41
+ #
42
+ # If the directory is relative, it implies it's the path from current directory.
43
+ # If the directory is absolute, it uses as it is.
44
+ #
45
+ # It respects file separator of the current operating system.
46
+ # A pattern like <tt>"path/to/files"</tt> will work both on *NIX and Windows machines.
47
+ #
48
+ # @param directory [String, Pathname] the directory
49
+ #
50
+ # @since 0.9.0
51
+ def self.require!(directory)
52
+ directory = directory.to_s.gsub(%r{(\/|\\)}, File::SEPARATOR)
53
+ directory = Pathname.new(Dir.pwd).join(directory).to_s
54
+ directory = File.join(directory, '**', '*.rb') unless directory =~ /(\*\*)/
55
+
56
+ FileList[directory].each { |file| require_relative file }
57
+ end
35
58
  end
36
59
  end
@@ -24,6 +24,28 @@ module Hanami
24
24
  "#<#{self.class}:#{'%x' % (__id__ << 1)}#{__inspect}>" # rubocop:disable Style/FormatString
25
25
  end
26
26
 
27
+ # Alias for __id__
28
+ #
29
+ # @return [Fixnum] the object id
30
+ #
31
+ # @since 0.9.0
32
+ #
33
+ # @see http://ruby-doc.org/core/Object.html#method-i-object_id
34
+ def object_id
35
+ __id__
36
+ end
37
+
38
+ # Interface for <tt>pp</pp>
39
+ #
40
+ # @return [String] the pretty printable inspection of the object
41
+ #
42
+ # @since 0.9.0
43
+ #
44
+ # @see https://ruby-doc.org/stdlib/libdoc/pp/rdoc/PP.html
45
+ def pretty_print(*)
46
+ inspect
47
+ end
48
+
27
49
  # Returns true if responds to the given method.
28
50
  #
29
51
  # @return [TrueClass,FalseClass] the result of the check
@@ -37,7 +37,7 @@ module Hanami
37
37
  when FalseClass, NilClass
38
38
  true
39
39
  else
40
- object.respond_to?(:empty?) ? !!object.empty? : !self
40
+ object.respond_to?(:empty?) ? object.empty? : !self
41
41
  end
42
42
  end
43
43
  end
@@ -38,7 +38,7 @@ module Hanami
38
38
  # # with missing constant
39
39
  # Hanami::Utils::Class.load!('Unknown') # => raises NameError
40
40
  def self.load!(name, namespace = Object)
41
- namespace.const_get(name.to_s)
41
+ namespace.const_get(name.to_s, false)
42
42
  end
43
43
 
44
44
  # Loads a class for the given name, only if it's defined.
@@ -69,7 +69,7 @@ module Hanami
69
69
  # # with explicit namespace
70
70
  # Hanami::Utils::Class.load('Service', App) # => App::Service
71
71
  def self.load(name, namespace = Object)
72
- load!(name, namespace) if namespace.const_defined?(name.to_s)
72
+ load!(name, namespace) if namespace.const_defined?(name.to_s, false)
73
73
  end
74
74
 
75
75
  # Loads a class from the given pattern name and namespace
@@ -112,7 +112,7 @@ module Hanami
112
112
  def self.load_from_pattern!(pattern, namespace = Object)
113
113
  String.new(pattern).tokenize do |token|
114
114
  begin
115
- return namespace.const_get(token)
115
+ return namespace.const_get(token, false)
116
116
  rescue NameError # rubocop:disable Lint/HandleExceptions
117
117
  end
118
118
  end
@@ -0,0 +1,20 @@
1
+ module Hanami
2
+ module Utils
3
+ # Ordered file list, consistent across operating systems
4
+ #
5
+ # @since 0.9.0
6
+ module FileList
7
+ # Return an ordered list of files, consistent across operating systems
8
+ #
9
+ # It has the same signature of <tt>Dir.glob</tt>, it just guarantees to
10
+ # order the results before to return them.
11
+ #
12
+ # @since 0.9.0
13
+ #
14
+ # @see https://ruby-doc.org/core/Dir.html#method-c-glob
15
+ def self.[](*args)
16
+ Dir.glob(*args).sort!
17
+ end
18
+ end
19
+ end
20
+ end
@@ -44,7 +44,7 @@ module Hanami
44
44
  #
45
45
  # hash.to_h # => { 'foo' => ['bar'] }
46
46
  def initialize(hash = {}, &blk)
47
- @hash = hash.to_h
47
+ @hash = hash.to_hash
48
48
  @hash.default_proc = blk
49
49
  end
50
50
 
@@ -65,7 +65,7 @@ module Hanami
65
65
  def symbolize!
66
66
  keys.each do |k|
67
67
  v = delete(k)
68
- v = self.class.new(v).symbolize! if v.is_a?(::Hash) || v.is_a?(self.class)
68
+ v = self.class.new(v).symbolize! if v.respond_to?(:to_hash)
69
69
 
70
70
  self[k.to_sym] = v
71
71
  end
@@ -90,7 +90,7 @@ module Hanami
90
90
  def stringify!
91
91
  keys.each do |k|
92
92
  v = delete(k)
93
- v = self.class.new(v).stringify! if v.is_a?(::Hash) || v.is_a?(self.class)
93
+ v = self.class.new(v).stringify! if v.respond_to?(:to_hash)
94
94
 
95
95
  self[k.to_s] = v
96
96
  end
@@ -224,7 +224,7 @@ module Hanami
224
224
  # @see http://www.ruby-doc.org/core/Hash.html#method-i-to_h
225
225
  def to_h
226
226
  @hash.each_with_object({}) do |(k, v), result|
227
- v = v.to_h if v.is_a?(self.class)
227
+ v = v.to_h if v.respond_to?(:to_hash)
228
228
  result[k] = v
229
229
  end
230
230
  end
@@ -278,13 +278,11 @@ module Hanami
278
278
  #
279
279
  # @raise [NoMethodError] If doesn't respond to the given method
280
280
  def method_missing(m, *args, &blk)
281
- if respond_to?(m)
282
- h = @hash.__send__(m, *args, &blk)
283
- h = self.class.new(h) if h.is_a?(::Hash)
284
- h
285
- else
286
- raise NoMethodError.new(%(undefined method `#{m}' for #{@hash}:#{self.class}))
287
- end
281
+ raise NoMethodError.new(%(undefined method `#{m}' for #{@hash}:#{self.class})) unless respond_to?(m)
282
+
283
+ h = @hash.__send__(m, *args, &blk)
284
+ h = self.class.new(h) if h.is_a?(::Hash)
285
+ h
288
286
  end
289
287
 
290
288
  # Override Ruby's respond_to_missing? in order to support ::Hash interface
@@ -10,8 +10,10 @@ require 'hanami/utils/string'
10
10
  # in coercions DSLs
11
11
  #
12
12
  # @since 0.3.0
13
- class Boolean
14
- end unless defined?(Boolean)
13
+ unless defined?(Boolean)
14
+ class Boolean
15
+ end
16
+ end
15
17
 
16
18
  module Hanami
17
19
  module Utils
@@ -110,7 +110,7 @@ module Hanami
110
110
  # paths = Hanami::Utils::LoadPaths.new
111
111
  # paths << '.' << '../..'
112
112
  def push(*paths)
113
- @paths.push(*paths) # rubocop:disable Performance/PushSplat
113
+ @paths.push(*paths)
114
114
  @paths = Kernel.Array(@paths)
115
115
  self
116
116
  end
@@ -399,13 +399,11 @@ module Hanami
399
399
  #
400
400
  # @raise [NoMethodError] If doesn't respond to the given method
401
401
  def method_missing(m, *args, &blk)
402
- if respond_to?(m)
403
- s = @string.__send__(m, *args, &blk)
404
- s = self.class.new(s) if s.is_a?(::String)
405
- s
406
- else
407
- raise NoMethodError.new(%(undefined method `#{m}' for "#{@string}":#{self.class}))
408
- end
402
+ raise NoMethodError.new(%(undefined method `#{m}' for "#{@string}":#{self.class})) unless respond_to?(m)
403
+
404
+ s = @string.__send__(m, *args, &blk)
405
+ s = self.class.new(s) if s.is_a?(::String)
406
+ s
409
407
  end
410
408
 
411
409
  # Override Ruby's respond_to_missing? in order to support ::String interface
@@ -3,6 +3,6 @@ module Hanami
3
3
  # Defines the version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '0.8.0'.freeze
6
+ VERSION = '0.9.0'.freeze
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-07-22 00:00:00.000000000 Z
13
+ date: 2016-11-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -66,6 +66,7 @@ files:
66
66
  - lib/hanami/utils/deprecation.rb
67
67
  - lib/hanami/utils/duplicable.rb
68
68
  - lib/hanami/utils/escape.rb
69
+ - lib/hanami/utils/file_list.rb
69
70
  - lib/hanami/utils/hash.rb
70
71
  - lib/hanami/utils/inflector.rb
71
72
  - lib/hanami/utils/io.rb
@@ -87,7 +88,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
87
88
  requirements:
88
89
  - - ">="
89
90
  - !ruby/object:Gem::Version
90
- version: 2.2.0
91
+ version: 2.3.0
91
92
  required_rubygems_version: !ruby/object:Gem::Requirement
92
93
  requirements:
93
94
  - - ">="