tins 1.43.0 → 1.44.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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.contexts/code_comment.rb +5 -8
  3. data/.contexts/lib.rb +0 -2
  4. data/CHANGES.md +12 -0
  5. data/README.md +158 -6
  6. data/Rakefile +19 -16
  7. data/examples/let.rb +8 -40
  8. data/examples/mail.rb +0 -1
  9. data/examples/turing.rb +3 -1
  10. data/lib/tins/alias.rb +1 -0
  11. data/lib/tins/annotate.rb +37 -27
  12. data/lib/tins/ask_and_send.rb +41 -0
  13. data/lib/tins/attempt.rb +39 -0
  14. data/lib/tins/bijection.rb +34 -0
  15. data/lib/tins/case_predicate.rb +21 -0
  16. data/lib/tins/complete.rb +16 -0
  17. data/lib/tins/concern.rb +64 -0
  18. data/lib/tins/date_dummy.rb +36 -4
  19. data/lib/tins/date_time_dummy.rb +34 -2
  20. data/lib/tins/deep_dup.rb +9 -2
  21. data/lib/tins/deprecate.rb +12 -0
  22. data/lib/tins/dslkit.rb +559 -83
  23. data/lib/tins/duration.rb +120 -5
  24. data/lib/tins/expose.rb +54 -5
  25. data/lib/tins/extract_last_argument_options.rb +9 -0
  26. data/lib/tins/file_binary.rb +104 -21
  27. data/lib/tins/find.rb +114 -11
  28. data/lib/tins/generator.rb +10 -2
  29. data/lib/tins/go.rb +81 -4
  30. data/lib/tins/hash_bfs.rb +4 -2
  31. data/lib/tins/hash_symbolize_keys_recursive.rb +62 -4
  32. data/lib/tins/hash_union.rb +47 -2
  33. data/lib/tins/if_predicate.rb +31 -0
  34. data/lib/tins/implement.rb +50 -0
  35. data/lib/tins/limited.rb +54 -5
  36. data/lib/tins/lines_file.rb +81 -2
  37. data/lib/tins/lru_cache.rb +54 -17
  38. data/lib/tins/memoize.rb +86 -58
  39. data/lib/tins/method_description.rb +87 -4
  40. data/lib/tins/minimize.rb +39 -11
  41. data/lib/tins/module_group.rb +27 -2
  42. data/lib/tins/named_set.rb +20 -0
  43. data/lib/tins/null.rb +86 -15
  44. data/lib/tins/once.rb +61 -4
  45. data/lib/tins/p.rb +44 -8
  46. data/lib/tins/partial_application.rb +66 -7
  47. data/lib/tins/proc_compose.rb +58 -1
  48. data/lib/tins/proc_prelude.rb +97 -10
  49. data/lib/tins/range_plus.rb +30 -2
  50. data/lib/tins/require_maybe.rb +36 -0
  51. data/lib/tins/responding.rb +39 -0
  52. data/lib/tins/secure_write.rb +24 -4
  53. data/lib/tins/sexy_singleton.rb +45 -48
  54. data/lib/tins/string_byte_order_mark.rb +33 -2
  55. data/lib/tins/string_camelize.rb +31 -2
  56. data/lib/tins/string_underscore.rb +33 -2
  57. data/lib/tins/string_version.rb +179 -10
  58. data/lib/tins/subhash.rb +35 -10
  59. data/lib/tins/temp_io.rb +7 -0
  60. data/lib/tins/temp_io_enum.rb +19 -0
  61. data/lib/tins/terminal.rb +31 -9
  62. data/lib/tins/thread_local.rb +67 -5
  63. data/lib/tins/time_dummy.rb +46 -21
  64. data/lib/tins/to.rb +15 -0
  65. data/lib/tins/to_proc.rb +17 -4
  66. data/lib/tins/token.rb +56 -1
  67. data/lib/tins/unit.rb +288 -149
  68. data/lib/tins/version.rb +1 -1
  69. data/lib/tins/write.rb +14 -3
  70. data/lib/tins/xt/blank.rb +81 -2
  71. data/lib/tins/xt/concern.rb +51 -0
  72. data/lib/tins/xt/full.rb +56 -11
  73. data/lib/tins/xt/irb.rb +46 -2
  74. data/lib/tins/xt/method_description.rb +0 -12
  75. data/lib/tins/xt/minimize.rb +7 -0
  76. data/lib/tins/xt/named.rb +71 -16
  77. data/lib/tins/xt/proc_compose.rb +4 -0
  78. data/lib/tins/xt/subhash.rb +11 -0
  79. data/lib/tins/xt/time_freezer.rb +43 -6
  80. data/lib/tins/xt.rb +1 -3
  81. data/lib/tins.rb +16 -3
  82. data/tests/duration_test.rb +4 -0
  83. data/tests/from_module_test.rb +30 -2
  84. data/tests/implement_test.rb +6 -8
  85. data/tests/lines_file_test.rb +2 -0
  86. data/tests/lru_cache_test.rb +12 -0
  87. data/tests/method_description_test.rb +14 -20
  88. data/tests/partial_application_test.rb +4 -0
  89. data/tests/proc_prelude_test.rb +1 -1
  90. data/tests/scope_test.rb +1 -1
  91. data/tests/string_version_test.rb +2 -0
  92. data/tests/to_test.rb +6 -6
  93. data/tins.gemspec +9 -9
  94. metadata +23 -41
  95. data/lib/tins/count_by.rb +0 -21
  96. data/lib/tins/deep_const_get.rb +0 -64
  97. data/lib/tins/timed_cache.rb +0 -51
  98. data/lib/tins/uniq_by.rb +0 -23
  99. data/lib/tins/xt/count_by.rb +0 -7
  100. data/lib/tins/xt/deep_const_get.rb +0 -7
  101. data/lib/tins/xt/uniq_by.rb +0 -25
  102. data/tests/count_by_test.rb +0 -17
  103. data/tests/deep_const_get_test.rb +0 -37
  104. data/tests/uniq_by_test.rb +0 -31
  105. /data/{COPYING → LICENSE} +0 -0
@@ -1,19 +1,70 @@
1
1
  require 'tins/concern'
2
2
 
3
3
  module Tins
4
+ # Concern provides a mechanism for module configuration that persists across
5
+ # inheritance and inclusion boundaries using thread-local storage.
6
+ #
7
+ # This module implements a pattern where modules can be configured with
8
+ # arguments that are then available throughout the module's lifecycle in
9
+ # a thread-safe manner. It's particularly useful for implementing
10
+ # configuration-based concerns that need to maintain state across
11
+ # different scopes.
12
+ #
13
+ # @example Configured concern usage
14
+ # module MyConcern
15
+ # extend Tins::Concern
16
+ # end
17
+ #
18
+ # # Configure the concern with parameters
19
+ # include MyConcern.tins_concern_configure(:option1, :option2)
4
20
  module Concern
21
+ # ModuleMixin provides thread-local storage for concern configuration.
22
+ #
23
+ # This mixin adds methods to any module that includes it, allowing for
24
+ # configuration of concerns through thread-local storage. The configuration
25
+ # is stored in the current thread's context and persists during the
26
+ # execution of code that uses this concern.
27
+ #
28
+ # @note This implementation relies on Thread.current which makes it
29
+ # thread-safe but scoped to individual threads.
5
30
  module ModuleMixin
31
+ # Configures the module with the given arguments and returns self.
32
+ #
33
+ # This method stores the provided arguments in thread-local storage,
34
+ # making them available via {tins_concern_args}. It's designed to be
35
+ # chainable (returns self).
36
+ #
37
+ # @param args [Array] Arguments to configure this concern with
38
+ # @return [Module] The module itself, for chaining
39
+ # @example
40
+ # MyConcern.tins_concern_configure(:option1, :option2)
6
41
  def tins_concern_configure(*args)
7
42
  Thread.current[:tin_concern_args] = args
8
43
  self
9
44
  end
10
45
 
46
+ # Retrieves the current concern configuration arguments.
47
+ #
48
+ # This method fetches the arguments that were previously set using
49
+ # {tins_concern_configure}. If no configuration has been set, it returns
50
+ # nil.
51
+ #
52
+ # @return [Array, nil] The stored configuration arguments or nil
53
+ # @example
54
+ # MyConcern.tins_concern_configure(:option1, :option2)
55
+ # puts MyConcern.tins_concern_args # => [:option1, :option2]
11
56
  def tins_concern_args
12
57
  Thread.current[:tin_concern_args]
13
58
  end
14
59
  end
15
60
  end
16
61
 
62
+ # Extends the core Module class with the concern functionality.
63
+ #
64
+ # This line makes the concern configuration methods available to all modules
65
+ # in the system, allowing any module to be configured as a concern.
66
+ #
67
+ # @see Tins::Concern::ModuleMixin
17
68
  class ::Module
18
69
  include Tins::Concern::ModuleMixin
19
70
  end
data/lib/tins/xt/full.rb CHANGED
@@ -1,18 +1,51 @@
1
1
  require 'tins/xt/blank'
2
2
 
3
3
  module Tins
4
+ # Provides methods for checking if objects are "full" (non-blank) and safely
5
+ # processing them in conditional contexts.
6
+ #
7
+ # This module adds the `full?` and `all_full?` methods to all objects, enabling
8
+ # clean, readable patterns for validation and conditional processing.
9
+ #
10
+ # @example Basic usage
11
+ # "hello".full? # => "hello"
12
+ # "".full? # => nil
13
+ #
14
+ # @example Method dispatch with block
15
+ # user.full?(:name) { |name| "Hello #{name}" } # Returns "Hello John" if name is full
16
+ #
17
+ # @example Safe assignment and processing
18
+ # if name = user.full?(:name)
19
+ # puts "Hello #{name}"
20
+ # end
4
21
  module Full
5
- # Returns the object if it isn't blank (as in Object#blank?), otherwise it
6
- # returns nil. If a block was given as an argument and the object isn't
7
- # blank, the block is executed with the object as its first argument. If an
8
- # argument +dispatch+ was given and the object wasn't blank the method
9
- # given by dispatch is called on the object. This is the same as
10
- # foo.full?(&:bar) in the previous block form.
22
+ # Checks if the object is not blank, returning the object itself if it's
23
+ # full, or nil if it's blank. If a method name is provided as +dispatch+,
24
+ # that method is called on the object and the result is checked for being
25
+ # full.
26
+ #
27
+ # @param dispatch [Symbol, nil] The method to call on the object (optional)
28
+ # @param args [Array] Arguments to pass to the dispatched method (optional)
29
+ # @yield [Object] Optional block to execute with the result if result or
30
+ # dispatched result not nil
31
+ # @return [Object, nil] The object itself if not blank, or the result of
32
+ # dispatching +dispatch+ if provided and valid, or nil if the object is blank
33
+ #
34
+ # @example Basic usage
35
+ # "hello".full? # => "hello"
36
+ # "".full? # => nil
37
+ #
38
+ # @example Method dispatch
39
+ # user.full?(:name) # Returns user.name if not blank, nil otherwise
40
+ #
41
+ # @example Method dispatch with arguments
42
+ # user.full?(:method_with_args, arg1, arg2)
43
+ #
44
+ # @example With block execution
45
+ # user.full?(:name) { |name| "Hello #{name}" }
11
46
  def full?(dispatch = nil, *args)
12
47
  if blank?
13
48
  obj = nil
14
- #elsif Module === dispatch # TODO
15
- # dispatch.found?(self)
16
49
  elsif dispatch
17
50
  obj = __send__(dispatch, *args)
18
51
  obj = nil if obj.blank?
@@ -26,14 +59,26 @@ module Tins
26
59
  end
27
60
  end
28
61
 
62
+ # Checks if all elements in a collection are "full" (not blank). If the
63
+ # object responds to +all?+ and all elements pass the +full?+ test, then
64
+ # the block is executed with the collection itself or the collection is returned.
65
+ #
66
+ # @return [Object, nil] The collection if all elements are full, otherwise nil
67
+ #
68
+ # @example Basic usage
69
+ # [1,2,3].all_full? # => [1,2,3]
70
+ # [1,nil,3].all_full? # => nil
71
+ #
72
+ # @example With block execution
73
+ # [1,2,3].all_full? { |array| array.sum }
29
74
  def all_full?
30
75
  if respond_to?(:all?) && all?(&:full?)
31
76
  block_given? ? yield(self) : self
32
77
  end
33
78
  end
34
- end
35
79
 
36
- class ::Object
37
- include Full
80
+ class ::Object
81
+ include Full
82
+ end
38
83
  end
39
84
  end
data/lib/tins/xt/irb.rb CHANGED
@@ -1,9 +1,42 @@
1
1
  require 'irb'
2
2
 
3
+ # Provides interactive debugging capabilities through the IRB console.
4
+ #
5
+ # This module adds an `examine` method to all objects, allowing developers to
6
+ # quickly drop into an interactive IRB session with the current binding or
7
+ # examine specific objects. It's particularly useful for debugging and exploring
8
+ # data structures during development.
9
+ #
10
+ # @example Basic usage
11
+ # # Drop into IRB with current context
12
+ # examine
13
+ #
14
+ # @example Examine a specific object
15
+ # data = [1, 2, 3]
16
+ # examine data # Inspects just the 'data' variable
17
+ #
18
+ # @example Use from within methods
19
+ # def process_data
20
+ # result = expensive_operation
21
+ # examine result # Debug the result immediately
22
+ # end
3
23
  module Tins
24
+ # We have our own IRB as well.
4
25
  IRB = ::IRB
5
26
 
27
+ # We extend the top level IRB module
6
28
  module ::IRB
29
+ # Starts an interactive IRB session with the given binding context. This
30
+ # method creates a new IRB instance and evaluates input from it, allowing for
31
+ # interactive exploration of variables and objects.
32
+ #
33
+ # @param binding [Binding, nil] The binding context to examine (defaults to TOPLEVEL_BINDING)
34
+ #
35
+ # @example Start IRB with current context
36
+ # examine
37
+ #
38
+ # @example Examine specific binding
39
+ # examine some_binding
7
40
  def self.examine(binding = TOPLEVEL_BINDING)
8
41
  setup nil
9
42
  workspace = WorkSpace.new binding
@@ -13,9 +46,20 @@ module Tins
13
46
  rescue Interrupt
14
47
  exit
15
48
  end
16
- end
17
49
 
18
- class ::Object
50
+ # Starts an interactive IRB session examining the current object and its context.
51
+ # This instance method provides a convenient way to debug objects without
52
+ # explicitly passing bindings.
53
+ #
54
+ # @param binding [Binding, nil] The binding context to examine (defaults to TOPLEVEL_BINDING)
55
+ # @return [void]
56
+ #
57
+ # @example Examine the current object
58
+ # my_object.examine
59
+ #
60
+ # @example Examine a specific variable
61
+ # data = [1, 2, 3]
62
+ # data.examine # Inspects just the 'data' variable
19
63
  def examine(binding = TOPLEVEL_BINDING)
20
64
  IRB.examine(binding)
21
65
  end
@@ -3,21 +3,9 @@ require 'tins/method_description'
3
3
  module Tins
4
4
  class ::UnboundMethod
5
5
  include MethodDescription
6
-
7
- alias to_s description
8
-
9
- def inspect
10
- "#<#{self.class}: #{description}>"
11
- end
12
6
  end
13
7
 
14
8
  class ::Method
15
9
  include MethodDescription
16
-
17
- alias to_s description
18
-
19
- def inspect
20
- "#<#{self.class}: #{description}>"
21
- end
22
10
  end
23
11
  end
@@ -0,0 +1,7 @@
1
+ require 'tins/minimize'
2
+
3
+ module Tins
4
+ class ::Array
5
+ include Tins::Minimize
6
+ end
7
+ end
data/lib/tins/xt/named.rb CHANGED
@@ -1,23 +1,78 @@
1
- require 'tins/xt/string_version'
1
+ module Tins
2
+ # A dynamically created module class used internally by the
3
+ # {Tins::Object#named} and {Tins::Module#named} methods to create dynamic
4
+ # methods.
5
+ #
6
+ # This class inherits from Module and serves as a template for creating
7
+ # dynamically scoped methods that can be extended or included into objects
8
+ # or classes.
9
+ Named = ::Class.new(::Module)
2
10
 
3
- class Object
4
- def named(name, method, *args, &named_block)
5
- extend Module.new {
6
- define_method(name) do |*rest, &block|
7
- block = named_block if named_block
8
- __send__(method, *(args + rest), &block)
11
+ class ::Object
12
+ # Adds a dynamically created method to the object instance. The method will
13
+ # call the specified +method+ with optional +args+ and combine any provided
14
+ # +named_block+ with runtime blocks.
15
+ #
16
+ # @param name [Symbol] The name of the method to create
17
+ # @param method [Symbol] The existing method to delegate to
18
+ # @param args [Array] Optional arguments to pre-bind to the delegated method
19
+ # @yield [Object] Optional block to be used as the method's block
20
+ # @return [Object] self
21
+ # @example Create a method that maps elements
22
+ # a = [1, 2, 3]
23
+ # a.named(:double, :map) { |x| x * 2 }
24
+ # a.double # => [2, 4, 6]
25
+ #
26
+ # @example Pre-bind arguments to a method
27
+ # def process(data, multiplier, &block)
28
+ # data.map { |x| block.call(x * multiplier) }
29
+ # end
30
+ #
31
+ # Object.named(:process_by_10, :process, 10) do |result|
32
+ # result + 1
33
+ # end
34
+ # process_by_10([1, 2, 3]) { |x| x * 2 } # => [21, 41, 61]
35
+ def named(name, method, *args, &named_block)
36
+ name = name.to_sym
37
+ m = Tins::Named.new {
38
+ define_method(name) do |*rest, &block|
39
+ block = named_block if named_block
40
+ __send__(method, *(args + rest), &block)
41
+ end
42
+ }
43
+ if m.respond_to?(:set_temporary_name)
44
+ m.set_temporary_name "#{m.class} for method #{name.inspect}"
9
45
  end
10
- }
46
+ extend m
47
+ end
11
48
  end
12
- end
13
49
 
14
- class Module
15
- def named(name, method, *args, &named_block)
16
- include Module.new {
17
- define_method(name) do |*rest, &block|
18
- block = named_block if named_block
19
- __send__(method, *(args + rest), &block)
50
+ class ::Module
51
+ # Adds a dynamically created method to all instances of the class. The
52
+ # method will call the specified +method+ with optional +args+ and combine
53
+ # any provided +named_block+ with runtime blocks.
54
+ #
55
+ # @param name [Symbol] The name of the method to create
56
+ # @param method [Symbol] The existing method to delegate to
57
+ # @param args [Array] Optional arguments to pre-bind to the delegated method
58
+ # @yield [Object] Optional block to be used as the method's block
59
+ # @return [Module] self
60
+ #
61
+ # @example Create a class-level method
62
+ # Array.named(:sum_all, :reduce) { |acc, x| acc + x }
63
+ # [1, 2, 3].sum_all # => 6
64
+ def named(name, method, *args, &named_block)
65
+ name = name.to_sym
66
+ m = Tins::Named.new {
67
+ define_method(name) do |*rest, &block|
68
+ block = named_block if named_block
69
+ __send__(method, *(args + rest), &block)
70
+ end
71
+ }
72
+ if m.respond_to?(:set_temporary_name)
73
+ m.set_temporary_name "#{m.class} for method #{name.inspect}"
20
74
  end
21
- }
75
+ include m
76
+ end
22
77
  end
23
78
  end
@@ -4,4 +4,8 @@ module Tins
4
4
  class ::Proc
5
5
  include Tins::ProcCompose
6
6
  end
7
+
8
+ class ::Method
9
+ include Tins::ProcCompose
10
+ end
7
11
  end
@@ -4,6 +4,17 @@ module Tins
4
4
  class ::Hash
5
5
  include Tins::Subhash
6
6
 
7
+ # The subhash! method creates a filtered subset of this hash based on the
8
+ # given patterns and replaces the current hash with the result.
9
+ #
10
+ # This method works by first calling subhash with the provided patterns to
11
+ # create a new hash containing only the matching key-value pairs, then
12
+ # replacing the contents of the current hash with those pairs.
13
+ #
14
+ # @param patterns [Array<Object>] One or more patterns to match against
15
+ # keys
16
+ # @return [Hash] Returns self after replacing its contents with the
17
+ # filtered subset
7
18
  def subhash!(*patterns)
8
19
  replace subhash(*patterns)
9
20
  end
@@ -2,12 +2,49 @@ require 'tins/xt/time_dummy'
2
2
  require 'tins/xt/date_time_dummy'
3
3
  require 'tins/xt/date_dummy'
4
4
 
5
- module Tins::TimeFreezer
6
- def self.freeze(time)
7
- Time.dummy(time) do
8
- DateTime.dummy(time) do
9
- Date.dummy(time) do
10
- yield
5
+ module Tins
6
+ # TimeFreezer provides a mechanism to temporarily freeze time across multiple
7
+ # time-related classes.
8
+ #
9
+ # This module allows you to temporarily replace the behavior of Time, DateTime,
10
+ # and Date classes with dummy implementations that always return a specific
11
+ # time value. This is particularly useful for testing code that depends on
12
+ # current time values.
13
+ #
14
+ # @example Basic usage
15
+ # Tins::TimeFreezer.freeze(Time.new(2023, 1, 1)) do
16
+ # # All Time, DateTime, and Date calls will return the frozen time
17
+ # puts Time.now # => 2023-01-01 00:00:00 +0000
18
+ # end
19
+ #
20
+ # @example With DateTime and Date
21
+ # Tins::TimeFreezer.freeze(Time.new(2023, 1, 1)) do
22
+ # puts DateTime.now # => 2023-01-01T00:00:00+00:00
23
+ # puts Date.today # => 2023-01-01
24
+ # end
25
+ #
26
+ # @example Using time string (will be parsed by Time.parse)
27
+ # Tins::TimeFreezer.freeze("2023-01-01 12:00:00") do
28
+ # # Time.now will return the parsed time
29
+ # puts Time.now # => 2023-01-01 12:00:00 +0000
30
+ # end
31
+ module TimeFreezer
32
+ # Freezes time for the duration of the given block.
33
+ #
34
+ # This method temporarily replaces the behavior of Time, DateTime, and Date
35
+ # classes with dummy implementations that always return the specified time
36
+ # value.
37
+ #
38
+ # @param time [Time, DateTime, Date] The time value to freeze all
39
+ # time-related classes to
40
+ # @yield [] The block of code to execute with frozen time
41
+ # @return [Object] The return value of the yielded block
42
+ def self.freeze(time)
43
+ Time.dummy(time) do
44
+ DateTime.dummy(time) do
45
+ Date.dummy(time) do
46
+ yield
47
+ end
11
48
  end
12
49
  end
13
50
  end
data/lib/tins/xt.rb CHANGED
@@ -3,7 +3,6 @@ require 'tins'
3
3
  module Tins
4
4
  require 'tins/xt/attempt'
5
5
  require 'tins/xt/blank'
6
- require 'tins/xt/count_by'
7
6
  require 'tins/xt/deep_dup'
8
7
  require 'tins/xt/file_binary'
9
8
  require 'tins/xt/full'
@@ -22,12 +21,10 @@ module Tins
22
21
  require 'tins/xt/time_dummy'
23
22
  require 'tins/xt/date_dummy'
24
23
  require 'tins/xt/date_time_dummy'
25
- require 'tins/xt/uniq_by'
26
24
  require 'tins/xt/write'
27
25
  require 'tins/xt/if_predicate'
28
26
  require 'tins/xt/ask_and_send'
29
27
  require 'tins/xt/extract_last_argument_options'
30
- require 'tins/xt/deep_const_get'
31
28
  require 'tins/xt/responding'
32
29
  require 'tins/xt/proc_compose'
33
30
  require 'tins/xt/proc_prelude'
@@ -44,4 +41,5 @@ module Tins
44
41
  require 'tins/xt/temp_io'
45
42
  require 'tins/xt/deprecate'
46
43
  require 'tins/xt/hash_bfs'
44
+ require 'tins/xt/minimize'
47
45
  end
data/lib/tins.rb CHANGED
@@ -1,7 +1,22 @@
1
+ # Tins is a collection of useful Ruby utilities and tools that provide
2
+ # common functionality without requiring external dependencies. It's designed
3
+ # to be a lightweight, drop-in library that enhances Ruby's standard library
4
+ # with practical conveniences.
5
+ #
6
+ # @example Basic usage
7
+ # require 'tins'
8
+ #
9
+ # Tins::Once.only_once { puts "Only one instance" }
10
+ #
11
+ # @example Automatic class extensions
12
+ # require 'tins/xt'
13
+ #
14
+ # # Automatically extends core classes with useful methods
15
+ # "foo".full? # => "foo"
16
+ # " ".full? # => nil
1
17
  module Tins
2
18
  require 'tins/attempt'
3
19
  require 'tins/bijection'
4
- require 'tins/count_by'
5
20
  require 'tins/deep_dup'
6
21
  require 'tins/file_binary'
7
22
  require 'tins/find'
@@ -31,11 +46,9 @@ module Tins
31
46
  require 'tins/date_dummy'
32
47
  require 'tins/date_time_dummy'
33
48
  require 'tins/to_proc'
34
- require 'tins/uniq_by'
35
49
  require 'tins/version'
36
50
  require 'tins/write'
37
51
  require 'tins/extract_last_argument_options'
38
- require 'tins/deep_const_get'
39
52
  require 'tins/responding'
40
53
  require 'tins/proc_compose'
41
54
  require 'tins/proc_prelude'
@@ -22,6 +22,10 @@ module Tins
22
22
  assert_equal '0+00:11:06.123456', Tins::Duration.new(666.123456).format
23
23
  end
24
24
 
25
+ def test_format_percentage
26
+ assert_equal '11%06', Tins::Duration.new(666.123456).format('%m%%%s')
27
+ end
28
+
25
29
  def test_smart_format
26
30
  assert_equal '00:11:06.123', Tins::Duration.new(666.123456).format('%D')
27
31
  assert_equal '7+17:11:06.123', Tins::Duration.new(666666.123456).format('%D')
@@ -11,6 +11,16 @@ class FromModuleTest < Test::Unit::TestCase
11
11
  end
12
12
  end
13
13
 
14
+ module MyIncludedModule2
15
+ def foo
16
+ :foo2
17
+ end
18
+
19
+ def bar
20
+ :bar2
21
+ end
22
+ end
23
+
14
24
  class MyKlass
15
25
  def foo
16
26
  :original_foo
@@ -35,14 +45,17 @@ class FromModuleTest < Test::Unit::TestCase
35
45
  def bar
36
46
  :original_bar
37
47
  end
48
+
49
+ def baz
50
+ :original_baz
51
+ end
38
52
  include MyIncludedModule
39
53
  end
40
54
 
41
55
  class AnotherDerivedKlass
42
- include MyModule
43
-
44
56
  extend Tins::FromModule
45
57
 
58
+ include MyModule
46
59
  include from module: MyIncludedModule, methods: :foo
47
60
  end
48
61
 
@@ -57,4 +70,19 @@ class FromModuleTest < Test::Unit::TestCase
57
70
  assert_equal :foo, c.foo
58
71
  assert_equal :original_bar, c.bar
59
72
  end
73
+
74
+ class MixedClass
75
+ extend Tins::FromModule
76
+
77
+ include MyModule
78
+ include from module: MyIncludedModule, methods: :foo
79
+ include from module: MyIncludedModule2, methods: :bar
80
+ end
81
+
82
+ def test_mixed_klass
83
+ c = MixedClass.new
84
+ assert_equal :foo, c.foo
85
+ assert_equal :bar2, c.bar
86
+ assert_equal :original_baz, c.baz
87
+ end
60
88
  end
@@ -53,14 +53,12 @@ module Tins
53
53
  assert_equal('blab', error_message { A.new.quux })
54
54
  end
55
55
 
56
- if RUBY_VERSION >= "2.1"
57
- def test_implement_def_subclass
58
- assert_equal(
59
- 'method foobar(arg1,arg2:?) has to be '\
60
- 'implemented in subclasses of Tins::ImplementTest::A',
61
- error_message { A.new.foobar }
62
- )
63
- end
56
+ def test_implement_def_subclass
57
+ assert_equal(
58
+ 'method foobar(arg1,arg2:…) has to be '\
59
+ 'implemented in subclasses of Tins::ImplementTest::A',
60
+ error_message { A.new.foobar }
61
+ )
64
62
  end
65
63
 
66
64
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  require 'test_helper'
2
4
  require 'tempfile'
3
5
 
@@ -6,6 +6,18 @@ module Tins
6
6
  @cache = LRUCache.new(3)
7
7
  end
8
8
 
9
+ def test_too_low_capacity
10
+ assert_raise ArgumentError do
11
+ LRUCache.new(0)
12
+ end
13
+ end
14
+
15
+ def test_wrong_capacity_type
16
+ assert_raise TypeError do
17
+ LRUCache.new(:foo)
18
+ end
19
+ end
20
+
9
21
  def test_can_be_filled_to_capacity
10
22
  assert_equal 0, @cache.size
11
23
  @cache[1] = 1
@@ -12,10 +12,8 @@ module Tins
12
12
  end
13
13
 
14
14
  def test_static_nonstatic
15
- assert_equal 'Tins::MethodDescriptionTest::A#foo()', A.instance_method(:foo).to_s
16
- assert_equal '#<UnboundMethod: Tins::MethodDescriptionTest::A#foo()>', A.instance_method(:foo).inspect
17
- assert_equal 'Tins::MethodDescriptionTest::A.foo()', A.method(:foo).to_s
18
- assert_equal '#<Method: Tins::MethodDescriptionTest::A.foo()>', A.method(:foo).inspect
15
+ assert_equal 'Tins::MethodDescriptionTest::A#foo()', A.instance_method(:foo).description
16
+ assert_equal 'Tins::MethodDescriptionTest::A.foo()', A.method(:foo).description
19
17
  end
20
18
 
21
19
  class B
@@ -33,12 +31,12 @@ module Tins
33
31
  end
34
32
 
35
33
  def test_standard_parameters_namespace
36
- assert_equal 'Tins::MethodDescriptionTest::B#foo(x,y=?,*r,&b)',
37
- B.instance_method(:foo).to_s
34
+ assert_equal 'Tins::MethodDescriptionTest::B#foo(x,y=…,*r,&b)',
35
+ B.instance_method(:foo).description
38
36
  end
39
37
 
40
38
  def test_standard_parameters_name
41
- assert_equal 'foo(x,y=?,*r,&b)',
39
+ assert_equal 'foo(x,y=…,*r,&b)',
42
40
  B.instance_method(:foo).description(style: :name)
43
41
  end
44
42
 
@@ -84,21 +82,17 @@ module Tins
84
82
  end
85
83
 
86
84
  def test_keyword_parameters
87
- assert_equal 'Tins::MethodDescriptionTest::C#foo(x,k:?,&b)', C.instance_method(:foo).to_s
88
- assert_equal 'Tins::MethodDescriptionTest::C#bar(x,**k,&b)', C.instance_method(:bar).to_s
85
+ assert_equal 'Tins::MethodDescriptionTest::C#foo(x,k:…,&b)', C.instance_method(:foo).description
86
+ assert_equal 'Tins::MethodDescriptionTest::C#bar(x,**k,&b)', C.instance_method(:bar).description
89
87
  end
90
88
 
91
- if RUBY_VERSION >= "2.1"
92
- eval %{
93
- class D
94
- def foo(x, k:, &b)
95
- end
96
- end
97
-
98
- def test_keyword_parameters_required
99
- assert_equal 'Tins::MethodDescriptionTest::D#foo(x,k:,&b)', D.instance_method(:foo).to_s
100
- end
101
- }
89
+ class D
90
+ def foo(x, k:, &b)
91
+ end
92
+ end
93
+
94
+ def test_keyword_parameters_required
95
+ assert_equal 'Tins::MethodDescriptionTest::D#foo(x,k:,&b)', D.instance_method(:foo).description
102
96
  end
103
97
  end
104
98
  end