modulation 0.24 → 0.25

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ef376ed9b8358f85facdb42d47fde2c5710ccec9e20ff3bff2657e17a392327
4
- data.tar.gz: 36b7033a8b9c44158f23b4bb3bc94a465bb123154d3712d79c654d237ce0061b
3
+ metadata.gz: 05eb758bd8b1f020ab36975897629ae0246a181e75d63e92707aa2fb47945d46
4
+ data.tar.gz: f17e7568e877cfdc6d8526976f895f3595364a7755aebda382922f4bd04967d4
5
5
  SHA512:
6
- metadata.gz: 3b739b962bb3565c333fa8da105cc82105079494b0ec274c1d1a01ee2791407c684504291674251c9f90342705659326a2921042274a6d9708e6f481497d8470
7
- data.tar.gz: dc907fc3091394365b7db34c8b0e68ac0374ecbf56e932c7a2a9bacffc9698d793a856618255730d73ed37c7ade9068c1b8e55719f09045a2c56da5d028565d9
6
+ metadata.gz: 7db683d75d02ef37ae637727537a6403cd69d506f7c6f359be5547e5f8fb05901256fb266ce4ea41dc987fc6c0976edd4f111d1ad11335a7164790a68d4a3742
7
+ data.tar.gz: be5d4e4c06983e19b1921cbb256bfa8162b6aa927eb14936f2ed8dda980715f7ac85d75eee321e0f39ae1b825fcf4be0b389c5976c476f838967d970e222fca9
data/CHANGELOG.md CHANGED
@@ -1,8 +1,13 @@
1
+ 0.25 2019-06-07
2
+ ---------------
3
+
4
+ * Add `#import_map` method
5
+
1
6
  0.24 2019-05-22
2
7
  ---------------
3
8
 
4
9
  * Fix usage of Modulation in rake tasks
5
- * Fix behavior when referencing missing consts in modules using `auto_import`
10
+ * Fix behavior when referencing missing consts in modules using `#auto_import`
6
11
 
7
12
  0.23 2019-05-17
8
13
  ---------------
@@ -58,9 +63,9 @@
58
63
  0.13 2018-09-06
59
64
  ---------------
60
65
 
61
- * Evaluate module code on singleton_class instead of using `extend self`
62
- * Fix calling `include` inside imported module
63
- * Add `rbm` binary for running ruby scripts using `import`
66
+ * Evaluate module code on singleton_class instead of using `#extend self`
67
+ * Fix calling `#include` inside imported module
68
+ * Add `rbm` binary for running ruby scripts using `#import`
64
69
 
65
70
  0.12 2018-08-20
66
71
  ---------------
@@ -103,19 +108,20 @@
103
108
  --------------
104
109
 
105
110
  * Add support for using gems as imported modules (experimental feature)
106
- * Add Modulation.full_trace! method for getting full backtrace on errors
107
- * Fix Modulation.transform_export_default_value
111
+ * Add `Modulation.full_trace!` method for getting full backtrace on errors
112
+ * Fix `Modulation.transform_export_default_value`
108
113
  * Change name to *Modulation*
109
114
 
110
115
  0.5.1 2018-07-20
111
116
  ----------------
112
117
 
113
- * Fix extend_from, include_from to work with ruby 2.4
118
+ * Fix `#extend_from`, `#include_from` to work with ruby 2.4
114
119
 
115
120
  0.5 2018-07-19
116
121
  --------------
117
122
 
118
- * Add extend_from, include_from to include imported methods in classes and modules
123
+ * Add `#extend_from`, `#include_from` to include imported methods in classes
124
+ and modules
119
125
 
120
126
  0.4 2018-07-19
121
127
  --------------
data/README.md CHANGED
@@ -28,21 +28,21 @@ a functional style, minimizing boilerplate code.
28
28
  ## Rationale
29
29
 
30
30
  You're probably asking yourself "what the ****?" , but when your Ruby app grows
31
- and is split into multiple files loaded using `require`, you'll soon hit some
31
+ and is split into multiple files loaded using `#require`, you'll soon hit some
32
32
  issues:
33
33
 
34
- - Once a file is `require`d, any class, module or constant in it is available
34
+ - Once a file is `#require`d, any class, module or constant in it is available
35
35
  to any other file in your codebase. All "globals" (classes, modules,
36
36
  constants) are loaded, well, globally, in a single namespace. Name conflicts
37
37
  are easy in Ruby.
38
38
  - To avoid class name conflicts, classes need to be nested under a single
39
39
  hierarchical tree, sometime reaching 4 levels or more. Just look at Rails.
40
- - Since a `require`d class or module can be loaded in any file and then made
40
+ - Since a `#require`d class or module can be loaded in any file and then made
41
41
  available to all files, it's easy to lose track of where it was loaded, and
42
42
  where it is used.
43
43
  - There's no easy way to hide implementation-specific classes or methods. Yes,
44
- there's `private`, `private_constant` etc, but by default everything is
45
- `public`!
44
+ there's `#private`, `#private_constant` etc, but by default everything is
45
+ `#public`!
46
46
  - Writing reusable functional code requires wrapping it in modules using
47
47
  `class << self`, `def self.foo ...`, `extend self` or `include Singleton`
48
48
  (the pain of implementing singletons in Ruby has been
@@ -54,7 +54,7 @@ issues:
54
54
  > name collision. Hopefully, the present gem could contribute to an eventual
55
55
  > "official" API.
56
56
 
57
- Personally, I have found that managing dependencies with `require` in large
57
+ Personally, I have found that managing dependencies with `#require` in large
58
58
  codebases is... not as elegant or painfree as I would expect from a
59
59
  first-class development environment. I also wanted to have a better solution
60
60
  for writing in a functional style.
@@ -108,7 +108,7 @@ operations such as [hot reloading](#reloading-modules).
108
108
 
109
109
  ### Exporting declarations
110
110
 
111
- Any class, module or constant be exported using `export`:
111
+ Any class, module or constant be exported using `#export`:
112
112
 
113
113
  ```ruby
114
114
  export :User, :Session
@@ -146,7 +146,7 @@ puts Seq.fib(10)
146
146
 
147
147
  ### Importing declarations
148
148
 
149
- Declarations from another module can be imported using `import`:
149
+ Declarations from another module can be imported using `#import`:
150
150
 
151
151
  ```ruby
152
152
  require 'modulation'
@@ -170,19 +170,36 @@ user = User.new(...)
170
170
  ```
171
171
 
172
172
  > **Note about paths**: module paths are always relative to the file
173
- > calling the `import` method, just like `require_relative`.
173
+ > calling the `#import` method, just like `#require_relative`.
174
174
 
175
175
  ### Importing all source files in a directory
176
176
 
177
- To load all source files in a directory you can use `import_all`:
177
+ To load all source files in a directory you can use `#import_all`:
178
178
 
179
179
  ```ruby
180
- import_all('./ext') # will load ./ext/kernel, ./ext/socket etc
180
+ import_all('./ext') # will load ./ext/kernel.rb, ./ext/socket.rb etc
181
+ ```
182
+
183
+ Groups of modules providing a uniform interface can also be loaded using
184
+ `#import_map`:
185
+
186
+ ```ruby
187
+ API = import_map('./math_api') #=> hash mapping filenames to modules
188
+ API.keys #=> ['add', 'mul', 'sub', 'div']
189
+ API['add'] #=> add module
190
+ ```
191
+
192
+ The `#import_map` takes an optional block to transform hash keys:
193
+
194
+ ```ruby
195
+ API = import_map('./math_api') { |name, mod| name.to_sym }
196
+ API.keys #=> [:add, :mul, :sub, :div]
197
+ API[:add] #=> add module
181
198
  ```
182
199
 
183
200
  ### Importing methods into classes and modules
184
201
 
185
- Modulation provides the `extend_from` and `include_from` methods to include
202
+ Modulation provides the `#extend_from` and `#include_from` methods to include
186
203
  imported methods in classes and modules:
187
204
 
188
205
  ```ruby
@@ -205,7 +222,7 @@ end
205
222
  5.seq(:fib)
206
223
  ```
207
224
 
208
- The `include_from` method accepts an optional list of symbols to import:
225
+ The `#include_from` method accepts an optional list of symbols to import:
209
226
 
210
227
  ```ruby
211
228
  class Integer
@@ -218,7 +235,7 @@ end
218
235
  ### Default exports
219
236
 
220
237
  A module may wish to expose just a single class or constant, in which case it
221
- can use `export_default`:
238
+ can use `#export_default`:
222
239
 
223
240
  *user.rb*
224
241
  ```ruby
@@ -295,7 +312,7 @@ what_is = ::THE_MEANING_OF_LIFE
295
312
 
296
313
  ### Unit testing modules
297
314
 
298
- Methods and constants that are not exported can be tested using the `__expose!`
315
+ Methods and constants that are not exported can be tested using the `#__expose!`
299
316
  method. Thus you can keep implementation details hidden, while being able to
300
317
  easily test them:
301
318
 
@@ -380,7 +397,7 @@ end
380
397
  > lazy-loaded constant from the module's top namespace, use the `MODULE`
381
398
  > namespace, as shown above.
382
399
 
383
- The `auto_import` method can also take a hash mapping constant names to paths.
400
+ The `#auto_import` method can also take a hash mapping constant names to paths.
384
401
  This is especially useful when multiple concerns are grouped under a single
385
402
  namespace:
386
403
 
@@ -440,7 +457,7 @@ settings = settings.__reload!
440
457
 
441
458
  Modulation can be used to write gems, providing fine-grained control over your
442
459
  gem's public APIs and letting you hide any implementation details. In order to
443
- allow loading a gem using either `require` or `import`, code your gem's main
460
+ allow loading a gem using either `#require` or `#import`, code your gem's main
444
461
  file normally, but add `require 'modulation/gem'` at the top, and export your
445
462
  gem's main namespace as a default export, e.g.:
446
463
 
@@ -458,7 +475,7 @@ end
458
475
 
459
476
  ## Importing gems using Modulation
460
477
 
461
- Gems written using modulation can also be loaded using `import`. If modulation
478
+ Gems written using modulation can also be loaded using `#import`. If modulation
462
479
  does not find the module specified by the given relative path, it will attempt
463
480
  to load a gem by the same name. It is also possible to load specific files
464
481
  inside modules by specifying a sub-path:
@@ -468,9 +485,9 @@ require 'modulation'
468
485
  MyFeature = import 'my_gem/my_feature'
469
486
  ```
470
487
 
471
- > **Note**: Since there's not much of a point in `import`ing gems that do not use
472
- > Modulation to export symbols, Modulation will refuse to import any gem that
473
- > does not depend on Modulation.
488
+ > **Note**: Since there's not much of a point in `#import`ing gems that do not
489
+ > use Modulation to export symbols, Modulation will refuse to import any gem
490
+ > that does not depend on Modulation.
474
491
 
475
492
  ## Coding style recommendations
476
493
 
@@ -480,8 +497,8 @@ MyFeature = import 'my_gem/my_feature'
480
497
  Settings = import('./settings')
481
498
  ```
482
499
 
483
- * Place your exports at the top of your module, followed by `require`s,
484
- followed by `import`s:
500
+ * Place your exports at the top of your module, followed by `#require`s,
501
+ followed by `#import`s:
485
502
 
486
503
  ```ruby
487
504
  export :foo, :bar, :baz
@@ -56,6 +56,21 @@ module Modulation
56
56
  end
57
57
  end
58
58
 
59
+ # Imports all source files in given directory, returning a hash mapping
60
+ # filenames to modules
61
+ # @ param path [String] relative directory path
62
+ # @param caller_location [String] caller location
63
+ # @return [Hash] hash mapping filenames to modules
64
+ def import_map(path, caller_location = caller(1..1).first)
65
+ abs_path = Paths.absolute_dir_path(path, caller_location)
66
+ Dir["#{abs_path}/**/*.rb"].each_with_object({}) do |fn, h|
67
+ mod = @loaded_modules[fn] || create_module_from_file(fn)
68
+ name = File.basename(fn) =~ /^(.+)\.rb$/ && $1
69
+ name = yield name, mod if block_given?
70
+ h[name] = mod
71
+ end
72
+ end
73
+
59
74
  # Adds all or part of a module's methods to a target object
60
75
  # If no symbols are given, all methods are added
61
76
  # @param mod [Module] imported module
@@ -17,6 +17,15 @@ module Kernel
17
17
  def import_all(path, caller_location = caller(1..1).first)
18
18
  Modulation.import_all(path, caller_location)
19
19
  end
20
+
21
+ # Imports all modules in given directory, returning a hash mapping filenames
22
+ # to modules
23
+ # @param path [String] directory path
24
+ # @param caller_location [String] caller location
25
+ # @return [Hash] hash mapping filenames to module objects
26
+ def import_map(path, caller_location = caller(1..1).first, &block)
27
+ Modulation.import_map(path, caller_location, &block)
28
+ end
20
29
  end
21
30
 
22
31
  # Module extensions
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Modulation
4
- VERSION = '0.24'
4
+ VERSION = '0.25'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: modulation
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.24'
4
+ version: '0.25'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-22 00:00:00.000000000 Z
11
+ date: 2019-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest