autoloaded 0.0.3

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 (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +3 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.yardopts +1 -0
  7. data/Gemfile +20 -0
  8. data/Guardfile +35 -0
  9. data/License.md +22 -0
  10. data/README.md +113 -0
  11. data/Rakefile +2 -0
  12. data/autoloaded.gemspec +41 -0
  13. data/lib/autoloaded.rb +33 -0
  14. data/lib/autoloaded/constant.rb +45 -0
  15. data/lib/autoloaded/refine.rb +9 -0
  16. data/lib/autoloaded/refine/string.rb +13 -0
  17. data/lib/autoloaded/refine/string/to_source_filename.rb +44 -0
  18. data/lib/autoloaded/version.rb +5 -0
  19. data/spec/autoloaded/constant_spec.rb +33 -0
  20. data/spec/autoloaded/refine/string/to_source_filename_spec.rb +21 -0
  21. data/spec/autoloaded/shallow_spec.rb +44 -0
  22. data/spec/autoloaded/version_spec.rb +5 -0
  23. data/spec/fixtures/filenames/AFilename.rb +0 -0
  24. data/spec/fixtures/filenames/a-file-name.rb +0 -0
  25. data/spec/fixtures/filenames/a-filename.rb +0 -0
  26. data/spec/fixtures/filenames/a_file_name.rb +0 -0
  27. data/spec/fixtures/filenames/a_filename.rb +0 -0
  28. data/spec/fixtures/namespace_that_is_autoloaded_conventionally.rb +7 -0
  29. data/spec/fixtures/namespace_that_is_autoloaded_conventionally/N-est-ed.rb +1 -0
  30. data/spec/fixtures/namespace_that_is_autoloaded_conventionally/nest_ed.rb +1 -0
  31. data/spec/fixtures/namespace_that_is_autoloaded_conventionally/nested.rb +5 -0
  32. data/spec/fixtures/namespace_that_is_autoloaded_unconventionally.rb +7 -0
  33. data/spec/fixtures/namespace_that_is_autoloaded_unconventionally/N-est-ed.rb +5 -0
  34. data/spec/fixtures/namespace_that_is_autoloaded_unconventionally/nest_ed.rb +1 -0
  35. data/spec/fixtures/namespace_that_is_not_autoloaded.rb +1 -0
  36. data/spec/fixtures/namespace_that_is_not_autoloaded/nested.rb +5 -0
  37. data/spec/matchers.rb +89 -0
  38. data/spec/spec_helper.rb +85 -0
  39. metadata +150 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 33eb826f0b852296da2a599fc26e5c474e05718c
4
+ data.tar.gz: d1cd5c7cd96613522d93559ee959f7d6a3197a3a
5
+ SHA512:
6
+ metadata.gz: 4c6050535f8b9948d416e63d8a0c9e9640eb37320b922995d6cded3e0fdba95f23494bb707bebd640f7fab079ee73ab0d3685f784a42a71731ed7eb18ff75d93
7
+ data.tar.gz: 0c1bbe28aa23983de38b5aff8972a6fa184b824c2e5ac801f852561f04c3f5737562c4daddea60f26b0b0ff2ef89261b0af90d9a2236c5b906b35d20c73231b7
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format doc
3
+ --require spec_helper
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ autoloaded
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.1.2
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --file License.md --no-private --protected --title "Autoloaded"
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :debug do
6
+ gem 'pry-byebug', '~> 2', platforms: [:mri_20, :mri_21]
7
+ gem 'pry-debugger', '~> 0', platforms: :mri_19
8
+ end
9
+
10
+ group :doc do
11
+ gem 'yard', '~> 0', require: false
12
+ gem 'rdiscount', '~> 2', require: false
13
+ end
14
+
15
+ group :tooling do
16
+ gem 'guard-rspec', '~> 4', require: false
17
+ if RUBY_PLATFORM =~ /darwin/i
18
+ gem 'rb-fsevent', '~> 0', require: false
19
+ end
20
+ end
data/Guardfile ADDED
@@ -0,0 +1,35 @@
1
+ interactor :off
2
+
3
+ debugger_gem = %w(pry-byebug pry-debugger).detect do |gem|
4
+ `bundle show #{gem} 2>&1 >/dev/null`
5
+ $?.success?
6
+ end
7
+ debugger_require = debugger_gem ? " --require #{debugger_gem}" : nil
8
+ guard :rspec, all_after_pass: true,
9
+ all_on_start: true,
10
+ cmd: "bundle exec rspec#{debugger_require} --format progress" do
11
+ # Run the corresponding spec (or all specs) when code changes.
12
+ watch( %r{^lib/(.+)\.rb$} ) do |match|
13
+ Dir["spec/#{match[1]}_spec.rb"].first || 'spec'
14
+ end
15
+
16
+ # Run a spec when it changes.
17
+ watch %r{^spec/.+_spec\.rb$}
18
+
19
+ # Run all specs when a shared spec changes.
20
+ watch( %r{^spec/.+_sharedspec\.rb$} ) { 'spec' }
21
+
22
+ # Run all specs when a matcher changes.
23
+ watch( 'spec/matchers.rb' ) { 'spec' }
24
+
25
+ # Run all when a fixture changes.
26
+ watch( %r{^spec/fixtures} ) { 'spec' }
27
+
28
+ # Run all specs when the RSpec configuration changes.
29
+ watch( '.rspec' ) { 'spec' }
30
+ watch( 'spec/spec_helper.rb' ) { 'spec' }
31
+
32
+ # Run all specs when the bundle changes.
33
+ watch( 'Gemfile.lock' ) { 'spec' }
34
+ watch( %r{^(.+)\.gemspec$} ) { 'spec' }
35
+ end
data/License.md ADDED
@@ -0,0 +1,22 @@
1
+ # The MIT License
2
+
3
+ Source code for _Autoloaded_ is Copyright © 2014
4
+ [Nils Jonsson](mailto:autoloaded@nilsjonsson.com) and
5
+ [contributors](https://github.com/njonsson/autoloaded/contributors "Autoloaded contributors at GitHub").
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
8
+ this software and associated documentation files (the “Software”), to deal in the
9
+ Software without restriction, including without limitation the rights to use,
10
+ copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
11
+ Software, and to permit persons to whom the Software is furnished to do so,
12
+ subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED “AS IS,” WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # Autoloaded
2
+
3
+ _Autoloaded_ dynamically and flexibly loads source files in a directory when a
4
+ corresponding constant is dereferenced. It offers several advantages over other
5
+ autoloading facilities such as those provided by the
6
+ [Ruby Core library](http://ruby-doc.org/core/Module.html#method-i-autoload) and
7
+ the
8
+ [ActiveSupport](http://api.rubyonrails.org/classes/ActiveSupport/Autoload.html)
9
+ gem:
10
+
11
+ * It does not require a separate `autoload` statement for each constant
12
+ * It does not enforce `CamelCase` to `snake_case` correspondence between the
13
+ names of constants and source files
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application’s Gemfile:
18
+
19
+ ```ruby
20
+ gem 'autoloaded', '~> 0'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install autoloaded
30
+
31
+ ## Usage
32
+
33
+ Suppose you have the following source files:
34
+
35
+ * lib/
36
+ * my_awesome_gem/
37
+ * db/
38
+ * mysql.rb
39
+ * postgresql.rb
40
+ * sql_server.rb
41
+ * db.rb
42
+ * my_awesome_gem.rb
43
+
44
+ The following statements establish autoloading — one statement per namespace:
45
+
46
+ ```ruby
47
+ # lib/my_awesome_gem.rb
48
+ module MyAwesomeGem
49
+
50
+ extend Autoloaded
51
+
52
+ end
53
+
54
+ # lib/my_awesome_gem/db.rb
55
+ module MyAwesomeGem
56
+
57
+ module DB
58
+
59
+ extend Autoloaded
60
+
61
+ end
62
+
63
+ end
64
+ ```
65
+
66
+ Note that your preferred casing of constants is accommodated automatically:
67
+
68
+ ```ruby
69
+ MyAwesomeGem::DB::MySQL.new
70
+ MyAwesomeGem::DB::PostgreSQL.new
71
+ MyAwesomeGem::DB::SQLServer.new
72
+ ```
73
+
74
+ _Autoloaded_ does not perform deep autoloading of nested namespaces and
75
+ directories. This is by design.
76
+
77
+ ### Important note
78
+
79
+ You must extend a namespace with _Autoloaded_ **from within the file in which the
80
+ namespace is defined**. This is because _Autoloaded_ utilizes the source file
81
+ path of the namespace to establish which directory will be autoloaded. That path
82
+ is discoverable only via the stack trace of `extend Autoloaded`.
83
+
84
+ In the following example, autoloading of the _MyAwesomeGem_ namespace will not
85
+ occur because the name of the source file in which the `extend` statement is
86
+ invoked does not match the name of the namespace.
87
+
88
+ ```ruby
89
+ # lib/my_awesome_gem.rb
90
+ module MyAwesomeGem; end
91
+
92
+ # lib/my_awesome_gem/db.rb
93
+ module MyAwesomeGem
94
+
95
+ # WRONG! Autoloading will not occur.
96
+ extend Autoloaded
97
+
98
+ module DB
99
+
100
+ extend Autoloaded
101
+
102
+ end
103
+
104
+ end
105
+ ```
106
+
107
+ ## Contributing
108
+
109
+ 1. [Fork the official repository](https://github.com/njonsson/autoloaded/fork).
110
+ 2. Create your feature branch: `git checkout -b my-new-feature`.
111
+ 3. Commit your changes: `git commit -am 'Add some feature'`.
112
+ 4. Push to the branch: `git push origin my-new-feature`.
113
+ 5. Create a [new pull request](https://github.com/njonsson/autoloaded/compare).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'autoloaded/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'autoloaded'
10
+ spec.version = Autoloaded::VERSION
11
+ spec.authors = ['Nils Jonsson']
12
+ spec.email = ['autoloaded@nilsjonsson.com']
13
+ spec.summary = <<-end_summary.gsub(/^\s+/, '').gsub("\n", ' ')
14
+ Dynamically and flexibly loads source files in a
15
+ directory when a corresponding constant is dereferenced.
16
+ end_summary
17
+ spec.description = spec.summary +
18
+ ' ' +
19
+ <<-end_description.gsub(/^\s+/, '').gsub(/\n(?=\S)/, ' ').chomp
20
+ Offers several advantages over other autoloading
21
+ facilities such as those provided by the Ruby Core
22
+ library and the ActiveSupport gem: (a) it does not
23
+ require a separate `autoload` statement for each
24
+ constant, and (b) it does not enforce CamelCase to
25
+ snake_case correspondence between the names of constants
26
+ and source files.
27
+ end_description
28
+ spec.homepage = 'https://github.com/njonsson/autoloaded'
29
+ spec.license = 'MIT'
30
+
31
+ spec.files = `git ls-files -z`.split("\x0")
32
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename f }
33
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
34
+ spec.require_paths = ['lib']
35
+
36
+ spec.required_ruby_version = '~> 2.1'
37
+
38
+ spec.add_development_dependency 'bundler', '~> 1'
39
+ spec.add_development_dependency 'rake', '~> 10'
40
+ spec.add_development_dependency 'rspec', '~> 3'
41
+ end
data/lib/autoloaded.rb ADDED
@@ -0,0 +1,33 @@
1
+ module Autoloaded
2
+
3
+ def self.extended(other_module)
4
+ caller_file_path = caller_locations.first.absolute_path
5
+ dir_path = "#{::File.dirname caller_file_path}/#{::File.basename caller_file_path, '.rb'}"
6
+ other_module.module_eval <<-end_module_eval, __FILE__, __LINE__
7
+ def self.autoload?(symbol)
8
+ #{dir_path.inspect}
9
+ end
10
+
11
+ def self.const_missing(symbol)
12
+ require 'autoloaded/constant'
13
+ ::Autoloaded::Constant.new(symbol).each_matching_filename_in #{dir_path.inspect} do |filename|
14
+ without_ext = "\#{::File.dirname filename}/\#{::File.basename filename}"
15
+ require without_ext
16
+ if const_defined?(symbol)
17
+ begin
18
+ return const_get(symbol)
19
+ rescue ::NameError
20
+ end
21
+ end
22
+ end
23
+
24
+ super symbol
25
+ end
26
+ end_module_eval
27
+ end
28
+
29
+ end
30
+
31
+ Dir.glob "#{File.dirname __FILE__}/#{File.basename __FILE__, '.rb'}/*.rb" do |f|
32
+ require_relative "#{File.basename __FILE__, '.rb'}/#{File.basename f, '.rb'}"
33
+ end
@@ -0,0 +1,45 @@
1
+ require 'autoloaded/refine/string/to_source_filename'
2
+ require 'set'
3
+
4
+ using ::Autoloaded::Refine::String::ToSourceFilename
5
+
6
+ module Autoloaded; end
7
+
8
+ class Autoloaded::Constant
9
+
10
+ attr_reader :name
11
+
12
+ def initialize(name)
13
+ @name = name
14
+ end
15
+
16
+ def each_matching_filename_in(directory)
17
+ filenames = ::Set.new
18
+
19
+ ::Dir.chdir directory do
20
+ filename = [name.to_s.to_source_filename, extension].join
21
+ if ::File.file?(filename) && filenames.add?(filename)
22
+ yield ::File.join(directory, filename)
23
+ end
24
+
25
+ name_signature = signature(name)
26
+ ::Dir.glob(['*', extension].join, ::File::FNM_CASEFOLD) do |f|
27
+ f_signature = signature(::File.basename(f, extension))
28
+ if (f_signature == name_signature) && filenames.add?(f)
29
+ yield ::File.join(directory, f)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def extension
38
+ '.rb'
39
+ end
40
+
41
+ def signature(string)
42
+ string.to_s.gsub(/[^a-z0-9]/i, '').downcase
43
+ end
44
+
45
+ end
@@ -0,0 +1,9 @@
1
+ module Autoloaded
2
+
3
+ module Refine; end
4
+
5
+ end
6
+
7
+ Dir.glob "#{File.dirname __FILE__}/#{File.basename __FILE__, '.rb'}/*.rb" do |f|
8
+ require_relative "#{File.basename __FILE__, '.rb'}/#{File.basename f, '.rb'}"
9
+ end
@@ -0,0 +1,13 @@
1
+ module Autoloaded
2
+
3
+ module Refine
4
+
5
+ module String; end
6
+
7
+ end
8
+
9
+ end
10
+
11
+ Dir.glob "#{File.dirname __FILE__}/#{File.basename __FILE__, '.rb'}/*.rb" do |f|
12
+ require_relative "#{File.basename __FILE__, '.rb'}/#{File.basename f, '.rb'}"
13
+ end
@@ -0,0 +1,44 @@
1
+ module Autoloaded
2
+
3
+ module Refine
4
+
5
+ module String; end
6
+
7
+ end
8
+
9
+ end
10
+
11
+ module Autoloaded::Refine::String::ToSourceFilename
12
+
13
+ refine ::String do
14
+ def replace_nonalphanumeric_sequence_with_separator
15
+ gsub(/[^a-z0-9]+/i, separator.to_s)
16
+ end
17
+
18
+ def separate_capital_and_following_capitalized_word
19
+ gsub(/([A-Z])([A-Z])([a-z])/,
20
+ "\\1#{separator}\\2\\3")
21
+ end
22
+
23
+ def separate_digit_and_following_letter
24
+ gsub(/([0-9])([a-z])/i, "\\1#{separator}\\2")
25
+ end
26
+
27
+ def separate_lowercase_letter_and_following_capital_letter
28
+ gsub(/([a-z])([A-Z])/, "\\1#{separator}\\2")
29
+ end
30
+
31
+ def separator
32
+ '_'
33
+ end
34
+
35
+ def to_source_filename
36
+ replace_nonalphanumeric_sequence_with_separator.
37
+ separate_capital_and_following_capitalized_word.
38
+ separate_lowercase_letter_and_following_capital_letter.
39
+ separate_digit_and_following_letter.
40
+ downcase
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,5 @@
1
+ module Autoloaded
2
+
3
+ VERSION = '0.0.3'
4
+
5
+ end
@@ -0,0 +1,33 @@
1
+ require 'autoloaded/constant'
2
+
3
+ RSpec.describe Autoloaded::Constant do
4
+ let(:constant_class) { described_class }
5
+
6
+ describe 'for' do
7
+ let(:directory) { 'spec/fixtures/filenames' }
8
+
9
+ {AFilename: %w(a_filename a-file-name a-filename a_file_name AFilename),
10
+ A_FILENAME: %w(a_filename a-file-name a-filename a_file_name AFilename),
11
+ AFileName: %w(a_file_name a-file-name a-filename a_filename AFilename),
12
+ AFILEName: %w(a-file-name a-filename a_file_name a_filename AFilename)}.each do |constant_name,
13
+ filenames|
14
+ describe constant_name.inspect do
15
+ let(:constant) { constant_class.new constant_name }
16
+
17
+ let(:full_filenames) {
18
+ filenames.collect do |filename|
19
+ "#{directory}/#{filename}.rb"
20
+ end
21
+ }
22
+
23
+ describe '#each_matching_filename_in' do
24
+ specify {
25
+ expect { |block|
26
+ constant.each_matching_filename_in(directory, &block)
27
+ }.to yield_successive_args(*full_filenames)
28
+ }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ require 'autoloaded/refine/string/to_source_filename'
2
+
3
+ using Autoloaded::Refine::String::ToSourceFilename
4
+
5
+ RSpec.describe Autoloaded::Refine::String::ToSourceFilename do
6
+ {'Foo' => 'foo',
7
+ 'IO' => 'io',
8
+ 'MySQL2' => 'my_sql2',
9
+ 'PostgreSQL' => 'postgre_sql',
10
+ 'Geo3D' => 'geo3_d',
11
+ 'Xfiles' => 'xfiles',
12
+ 'XFiles' => 'x_files',
13
+ 'FOOBar' => 'foo_bar',
14
+ 'FOO_BAR' => 'foo_bar'}.each do |constant_name, filename|
15
+ describe "for #{constant_name.inspect}" do
16
+ describe '#to_source_filename' do
17
+ specify { expect(constant_name.to_source_filename).to eq(filename) }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ require 'autoloaded'
2
+ require 'matchers'
3
+
4
+ RSpec.describe Autoloaded do
5
+ describe 'not included in a namespace' do
6
+ let(:source_file) { 'spec/fixtures/namespace_that_is_not_autoloaded.rb' }
7
+
8
+ specify('does not dynamically define a nested constant') {
9
+ expect(source_file).not_to autoload_a_constant_named('NamespaceThatIsNotAutoloaded::Nested')
10
+ }
11
+ end
12
+
13
+ describe 'included in a namespace' do
14
+ describe 'whose source files have conventional names' do
15
+ let(:source_file) {
16
+ 'spec/fixtures/namespace_that_is_autoloaded_conventionally.rb'
17
+ }
18
+
19
+ specify('dynamically defines a nested constant stored in a conventionally-named file') {
20
+ expect(source_file).to autoload_a_constant_named('NamespaceThatIsAutoloadedConventionally::Nested')
21
+ }
22
+
23
+ specify('does not pollute the namespace') {
24
+ expect(source_file).to define_only_constants_named(:Nested).
25
+ in_a_namespace_named(:NamespaceThatIsAutoloadedConventionally)
26
+ }
27
+ end
28
+
29
+ describe 'whose source files have unconventional names' do
30
+ let(:source_file) {
31
+ 'spec/fixtures/namespace_that_is_autoloaded_unconventionally.rb'
32
+ }
33
+
34
+ specify('dynamically defines a nested constant stored in a unconventionally-named file') {
35
+ expect(source_file).to autoload_a_constant_named('NamespaceThatIsAutoloadedUnconventionally::Nested')
36
+ }
37
+
38
+ specify('does not pollute the namespace') {
39
+ expect(source_file).to define_only_constants_named(:Nested).
40
+ in_a_namespace_named(:NamespaceThatIsAutoloadedUnconventionally)
41
+ }
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,5 @@
1
+ require 'autoloaded/version'
2
+
3
+ RSpec.describe "#{Autoloaded.name}::VERSION" do
4
+ specify { expect(Autoloaded::VERSION).to match( /^\d+\.\d+\.\d+/ ) }
5
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ require 'autoloaded'
2
+
3
+ module NamespaceThatIsAutoloadedConventionally
4
+
5
+ extend ::Autoloaded
6
+
7
+ end
@@ -0,0 +1 @@
1
+ raise "The file #{__FILE__} should not have been loaded"
@@ -0,0 +1 @@
1
+ raise "The file #{__FILE__} should not have been loaded"
@@ -0,0 +1,5 @@
1
+ module NamespaceThatIsAutoloadedConventionally
2
+
3
+ module Nested; end
4
+
5
+ end
@@ -0,0 +1,7 @@
1
+ require 'autoloaded'
2
+
3
+ module NamespaceThatIsAutoloadedUnconventionally
4
+
5
+ extend ::Autoloaded
6
+
7
+ end
@@ -0,0 +1,5 @@
1
+ module NamespaceThatIsAutoloadedUnconventionally
2
+
3
+ module Nested; end
4
+
5
+ end
@@ -0,0 +1 @@
1
+ raise "The file #{__FILE__} should not have been loaded"
@@ -0,0 +1 @@
1
+ module NamespaceThatIsNotAutoloaded; end
@@ -0,0 +1,5 @@
1
+ module NamespaceThatIsNotAutoloaded
2
+
3
+ module Nested; end
4
+
5
+ end
data/spec/matchers.rb ADDED
@@ -0,0 +1,89 @@
1
+ require 'open3'
2
+
3
+ RSpec::Matchers.define :autoload_a_constant_named do |constant_name|
4
+ match do |source_file|
5
+ # Ensure the file exists.
6
+ File.read source_file
7
+
8
+ constant_tokens = constant_name.split('::')
9
+ constant_up_till_last = constant_tokens[0...-1].join('::')
10
+ constant_last = constant_tokens.last
11
+ assertion = <<-end_assertion.gsub(/^ /, '')
12
+ begin;
13
+ #{constant_name};
14
+ rescue;
15
+ else;
16
+ raise('Constant #{constant_name} is already defined');
17
+ end;
18
+
19
+ load #{source_file.inspect};
20
+
21
+ puts(begin;
22
+ #{constant_name};
23
+ rescue;
24
+ 'false';
25
+ else;
26
+ #{constant_up_till_last}.autoload?(:#{constant_last}) ?
27
+ 'true' :
28
+ 'false';
29
+ end)
30
+ end_assertion
31
+ quoted_assertion = assertion.chomp.inspect.gsub('\n', "\n")
32
+ Open3.popen3 "bundle exec ruby -e #{quoted_assertion}" do |stdin,
33
+ stdout,
34
+ stderr|
35
+ if (stderr_output = stderr.read.chomp).empty?
36
+ eval stdout.read.chomp
37
+ else
38
+ raise stderr_output
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ RSpec::Matchers.define :define_only_constants_named do |*constant_names|
45
+ attr_reader :expected_constants, :extraneous_defined_constants, :namespace_name
46
+
47
+ match do |source_file|
48
+ # Ensure the file exists.
49
+ File.read source_file
50
+
51
+ unless namespace_name
52
+ raise "Missing .in_a_namespace_named(:Namespace) clause"
53
+ end
54
+
55
+ assertion = <<-end_assertion.gsub(/^ /, '')
56
+ load #{source_file.inspect};
57
+
58
+ puts(begin;
59
+ #{constant_names.inspect}.each do |constant_name|
60
+ #{namespace_name}.const_get constant_name;
61
+ end;
62
+ #{namespace_name}.constants.inspect;
63
+ rescue;
64
+ '[]';
65
+ end)
66
+ end_assertion
67
+ quoted_assertion = assertion.chomp.inspect.gsub('\n', "\n")
68
+ Open3.popen3 "bundle exec ruby -e #{quoted_assertion}" do |stdin,
69
+ stdout,
70
+ stderr|
71
+ if (stderr_output = stderr.read.chomp).empty?
72
+ defined_constants = Array(eval(stdout.read.chomp)).sort.collect(&:to_sym)
73
+ @expected_constants = constant_names.sort.collect(&:to_sym)
74
+ @extraneous_defined_constants = defined_constants - expected_constants
75
+ extraneous_defined_constants.empty?
76
+ else
77
+ raise stderr_output
78
+ end
79
+ end
80
+ end
81
+
82
+ chain :in_a_namespace_named do |namespace_name|
83
+ @namespace_name = namespace_name
84
+ end
85
+
86
+ failure_message do |source_file|
87
+ "expected only #{expected_constants.join ' and '} to be defined in #{namespace_name} but also found #{extraneous_defined_constants.join ' and '}"
88
+ end
89
+ end
@@ -0,0 +1,85 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
4
+ # file to always be loaded, without a need to explicitly require it in any files.
5
+ #
6
+ # Given that it is always loaded, you are encouraged to keep this file as
7
+ # light-weight as possible. Requiring heavyweight dependencies from this file
8
+ # will add to the boot time of your test suite on EVERY test run, even for an
9
+ # individual file that may not need all of that loaded. Instead, consider making
10
+ # a separate helper file that requires the additional dependencies and performs
11
+ # the additional setup, and require it from the spec files that actually need it.
12
+ #
13
+ # The `.rspec` file also contains a few flags that are not defaults but that
14
+ # users commonly want.
15
+ #
16
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
17
+ RSpec.configure do |config|
18
+ # rspec-expectations config goes here. You can use an alternate
19
+ # assertion/expectation library such as wrong or the stdlib/minitest
20
+ # assertions if you prefer.
21
+ config.expect_with :rspec do |expectations|
22
+ # This option will default to `true` in RSpec 4. It makes the `description`
23
+ # and `failure_message` of custom matchers include text for helper methods
24
+ # defined using `chain`, e.g.:
25
+ # be_bigger_than(2).and_smaller_than(4).description
26
+ # # => "be bigger than 2 and smaller than 4"
27
+ # ...rather than:
28
+ # # => "be bigger than 2"
29
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
30
+ end
31
+
32
+ # rspec-mocks config goes here. You can use an alternate test double
33
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
34
+ config.mock_with :rspec do |mocks|
35
+ # Prevents you from mocking or stubbing a method that does not exist on
36
+ # a real object. This is generally recommended, and will default to
37
+ # `true` in RSpec 4.
38
+ mocks.verify_partial_doubles = true
39
+ end
40
+
41
+ # These two settings work together to allow you to limit a spec run
42
+ # to individual examples or groups you care about by tagging them with
43
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
44
+ # get run.
45
+ config.filter_run :focus
46
+ config.run_all_when_everything_filtered = true
47
+
48
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
49
+ # For more details, see:
50
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
51
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
52
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
53
+ config.disable_monkey_patching!
54
+
55
+ # This setting enables warnings. It's recommended, but in some cases may
56
+ # be too noisy due to issues in dependencies.
57
+ # config.warnings = true
58
+
59
+ # Many RSpec users commonly either run the entire suite or an individual
60
+ # file, and it's useful to allow more verbose output when running an
61
+ # individual spec file.
62
+ if config.files_to_run.one?
63
+ # Use the documentation formatter for detailed output,
64
+ # unless a formatter has already been configured
65
+ # (e.g. via a command-line flag).
66
+ config.default_formatter = 'doc'
67
+ end
68
+
69
+ # Print the 10 slowest examples and example groups at the
70
+ # end of the spec run, to help surface which specs are running
71
+ # particularly slow.
72
+ config.profile_examples = 1
73
+
74
+ # Run specs in random order to surface order dependencies. If you find an
75
+ # order dependency and want to debug it, you can fix the order by providing
76
+ # the seed, which is printed after each run.
77
+ # --seed 1234
78
+ config.order = :random
79
+
80
+ # Seed global randomization in this process using the `--seed` CLI option.
81
+ # Setting this allows you to use `--seed` to deterministically reproduce
82
+ # test failures related to randomization by passing the same `--seed` value
83
+ # as the one that triggered the failure.
84
+ Kernel.srand config.seed
85
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: autoloaded
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Nils Jonsson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3'
55
+ description: 'Dynamically and flexibly loads source files in a directory when a corresponding
56
+ constant is dereferenced. Offers several advantages over other autoloading facilities
57
+ such as those provided by the Ruby Core library and the ActiveSupport gem: (a) it
58
+ does not require a separate `autoload` statement for each constant, and (b) it does
59
+ not enforce CamelCase to snake_case correspondence between the names of constants
60
+ and source files.'
61
+ email:
62
+ - autoloaded@nilsjonsson.com
63
+ executables: []
64
+ extensions: []
65
+ extra_rdoc_files: []
66
+ files:
67
+ - .gitignore
68
+ - .rspec
69
+ - .ruby-gemset
70
+ - .ruby-version
71
+ - .yardopts
72
+ - Gemfile
73
+ - Guardfile
74
+ - License.md
75
+ - README.md
76
+ - Rakefile
77
+ - autoloaded.gemspec
78
+ - lib/autoloaded.rb
79
+ - lib/autoloaded/constant.rb
80
+ - lib/autoloaded/refine.rb
81
+ - lib/autoloaded/refine/string.rb
82
+ - lib/autoloaded/refine/string/to_source_filename.rb
83
+ - lib/autoloaded/version.rb
84
+ - spec/autoloaded/constant_spec.rb
85
+ - spec/autoloaded/refine/string/to_source_filename_spec.rb
86
+ - spec/autoloaded/shallow_spec.rb
87
+ - spec/autoloaded/version_spec.rb
88
+ - spec/fixtures/filenames/AFilename.rb
89
+ - spec/fixtures/filenames/a-file-name.rb
90
+ - spec/fixtures/filenames/a-filename.rb
91
+ - spec/fixtures/filenames/a_file_name.rb
92
+ - spec/fixtures/filenames/a_filename.rb
93
+ - spec/fixtures/namespace_that_is_autoloaded_conventionally.rb
94
+ - spec/fixtures/namespace_that_is_autoloaded_conventionally/N-est-ed.rb
95
+ - spec/fixtures/namespace_that_is_autoloaded_conventionally/nest_ed.rb
96
+ - spec/fixtures/namespace_that_is_autoloaded_conventionally/nested.rb
97
+ - spec/fixtures/namespace_that_is_autoloaded_unconventionally.rb
98
+ - spec/fixtures/namespace_that_is_autoloaded_unconventionally/N-est-ed.rb
99
+ - spec/fixtures/namespace_that_is_autoloaded_unconventionally/nest_ed.rb
100
+ - spec/fixtures/namespace_that_is_not_autoloaded.rb
101
+ - spec/fixtures/namespace_that_is_not_autoloaded/nested.rb
102
+ - spec/matchers.rb
103
+ - spec/spec_helper.rb
104
+ homepage: https://github.com/njonsson/autoloaded
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ~>
115
+ - !ruby/object:Gem::Version
116
+ version: '2.1'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.2.2
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: Dynamically and flexibly loads source files in a directory when a corresponding
128
+ constant is dereferenced.
129
+ test_files:
130
+ - spec/autoloaded/constant_spec.rb
131
+ - spec/autoloaded/refine/string/to_source_filename_spec.rb
132
+ - spec/autoloaded/shallow_spec.rb
133
+ - spec/autoloaded/version_spec.rb
134
+ - spec/fixtures/filenames/AFilename.rb
135
+ - spec/fixtures/filenames/a-file-name.rb
136
+ - spec/fixtures/filenames/a-filename.rb
137
+ - spec/fixtures/filenames/a_file_name.rb
138
+ - spec/fixtures/filenames/a_filename.rb
139
+ - spec/fixtures/namespace_that_is_autoloaded_conventionally.rb
140
+ - spec/fixtures/namespace_that_is_autoloaded_conventionally/N-est-ed.rb
141
+ - spec/fixtures/namespace_that_is_autoloaded_conventionally/nest_ed.rb
142
+ - spec/fixtures/namespace_that_is_autoloaded_conventionally/nested.rb
143
+ - spec/fixtures/namespace_that_is_autoloaded_unconventionally.rb
144
+ - spec/fixtures/namespace_that_is_autoloaded_unconventionally/N-est-ed.rb
145
+ - spec/fixtures/namespace_that_is_autoloaded_unconventionally/nest_ed.rb
146
+ - spec/fixtures/namespace_that_is_not_autoloaded.rb
147
+ - spec/fixtures/namespace_that_is_not_autoloaded/nested.rb
148
+ - spec/matchers.rb
149
+ - spec/spec_helper.rb
150
+ has_rdoc: