autoloaded 1.6.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +8 -4
  3. data/.rspec +1 -1
  4. data/.travis.yml +1 -14
  5. data/Gemfile +10 -11
  6. data/Guardfile +22 -21
  7. data/History.md +12 -27
  8. data/README.md +48 -58
  9. data/Rakefile +0 -4
  10. data/autoloaded.gemspec +37 -41
  11. data/lib/autoloaded.rb +0 -40
  12. data/lib/autoloaded/autoloader.rb +8 -31
  13. data/lib/autoloaded/deprecation.rb +20 -11
  14. data/lib/autoloaded/inflection.rb +9 -7
  15. data/lib/autoloaded/load_pathed_directory.rb +4 -2
  16. data/lib/autoloaded/specification.rb +0 -2
  17. data/lib/autoloaded/specifications.rb +10 -16
  18. data/lib/autoloaded/version.rb +1 -1
  19. data/lib/autoloaded/warning.rb +44 -26
  20. data/lib/tasks/lib_each.rake +3 -15
  21. data/lib/tasks/spec.rake +6 -3
  22. data/spec/autoloaded/autoloader_spec.rb +469 -0
  23. data/spec/autoloaded/inflection_spec.rb +30 -0
  24. data/spec/autoloaded/load_pathed_directory_spec.rb +120 -0
  25. data/spec/autoloaded/specification_spec.rb +98 -0
  26. data/spec/autoloaded/specifications_spec.rb +191 -0
  27. data/spec/autoloaded/version_spec.rb +3 -0
  28. data/spec/autoloaded/warning_spec.rb +115 -0
  29. data/spec/autoloaded_macro_sharedspec.rb +24 -0
  30. data/spec/autoloaded_spec.rb +173 -0
  31. data/spec/fixtures/autoloaded_with_conventional_filename.rb +12 -0
  32. data/spec/fixtures/autoloaded_with_conventional_filename/N-est-ed.rb +1 -0
  33. data/spec/fixtures/autoloaded_with_conventional_filename/nest_ed.rb +1 -0
  34. data/spec/fixtures/autoloaded_with_conventional_filename/nested.rb +16 -0
  35. data/spec/fixtures/autoloaded_with_conventional_filename/nested/doubly_nested.rb +9 -0
  36. data/spec/fixtures/autoloaded_with_conventional_filename/old_school_autoload.rb +5 -0
  37. data/spec/fixtures/autoloaded_with_unconventional_filename.rb +12 -0
  38. data/spec/fixtures/autoloaded_with_unconventional_filename/N-est-ed.rb +7 -0
  39. data/spec/fixtures/autoloaded_with_unconventional_filename/nest_ed.rb +1 -0
  40. data/spec/fixtures/autoloaded_with_unconventional_filename/old_school_autoload.rb +5 -0
  41. data/spec/fixtures/filenames/AFilename.rb +0 -0
  42. data/spec/fixtures/filenames/a-file-name.rb +0 -0
  43. data/spec/fixtures/filenames/a-filename.rb +0 -0
  44. data/spec/fixtures/filenames/a_file_name.rb +0 -0
  45. data/spec/fixtures/filenames/a_filename.rb +0 -0
  46. data/spec/fixtures/filenames/afile-name.rb +0 -0
  47. data/spec/fixtures/filenames/afile_name.rb +0 -0
  48. data/spec/fixtures/not_autoloaded.rb +5 -0
  49. data/spec/fixtures/not_autoloaded/nested.rb +1 -0
  50. data/spec/fixtures/not_autoloaded/old_school_autoload.rb +5 -0
  51. data/spec/matchers.rb +85 -0
  52. data/spec/spec_helper.rb +91 -0
  53. data/spec/support/util.rb +42 -0
  54. data/spec/support/without_side_effects.rb +37 -0
  55. metadata +86 -22
  56. data/bin/console +0 -10
  57. data/bin/setup +0 -8
  58. data/lib/autoloaded/compatibility/refine_and_using.rb +0 -19
  59. data/lib/autoloaded/constant.rb +0 -94
  60. data/lib/autoloaded/refine.rb +0 -16
  61. data/lib/autoloaded/refine/string.rb +0 -20
  62. data/lib/autoloaded/refine/string/to_source_filename.rb +0 -58
@@ -0,0 +1,24 @@
1
+ RSpec.shared_examples_for "an #{Autoloaded.name} macro" do |macro|
2
+ before :each do
3
+ allow(autoloader_class).to receive(:new).and_return(autoloader)
4
+ allow_any_instance_of(autoloader_class).to receive(:autoload!)
5
+ end
6
+
7
+ let(:autoloaded_module) { Autoloaded }
8
+
9
+ let(:autoloader) { autoloader_class.new binding }
10
+
11
+ let(:autoloader_class) { autoloaded_module::Autoloader }
12
+
13
+ specify("yields an #{Autoloaded::Autoloader.name}") {
14
+ autoloaded_module.send macro do |autoloaded|
15
+ expect(autoloaded).to equal(autoloader)
16
+ end
17
+ }
18
+
19
+ specify("calls #{Autoloaded::Autoloader.name}#autoload!") {
20
+ expect(autoloader).to receive(:autoload!)
21
+ autoloaded_module.send macro do |autoloaded|
22
+ end
23
+ }
24
+ end
@@ -0,0 +1,173 @@
1
+ require 'autoloaded_macro_sharedspec'
2
+ require 'matchers'
3
+ require 'stringio'
4
+
5
+ RSpec.describe Autoloaded do
6
+ let(:autoloaded_module) { described_class }
7
+
8
+ let(:warning_module) { autoloaded_module::Warning }
9
+
10
+ describe '.class' do
11
+ it_behaves_like "an #{Autoloaded.name} macro", :class
12
+ end
13
+
14
+ describe '.module' do
15
+ it_behaves_like "an #{Autoloaded.name} macro", :module
16
+ end
17
+
18
+ describe '.warn' do
19
+ describe 'simple form' do
20
+ before :each do
21
+ allow(warning_module).to receive(:enable).
22
+ and_return(:warning_enable_result)
23
+ end
24
+
25
+ specify("delegates to #{Autoloaded::Warning.name}.enable") {
26
+ expect(warning_module).to receive(:enable).
27
+ with('foo').
28
+ and_return(:warning_enable_result)
29
+ autoloaded_module.warn 'foo'
30
+ }
31
+
32
+ specify("returns #{Autoloaded.name}") {
33
+ expect(autoloaded_module.warn('foo')).to eq(autoloaded_module)
34
+ }
35
+ end
36
+
37
+ describe 'block form' do
38
+ specify("delegates to #{Autoloaded::Warning.name}.enable") {
39
+ expect(warning_module).to receive(:enable).
40
+ with('foo').
41
+ and_yield.
42
+ and_return(:warning_enable_result)
43
+ result = autoloaded_module.warn('foo') do
44
+ :block_result
45
+ end
46
+ expect(result).to eq(:warning_enable_result)
47
+ }
48
+ end
49
+ end
50
+
51
+ describe '.warn?' do
52
+ specify("delegates to #{Autoloaded::Warning.name}.enabled?") {
53
+ expect(warning_module).to receive(:enabled?).
54
+ and_return(:warning_enabled_result)
55
+ expect(autoloaded_module.warn?).to eq(:warning_enabled_result)
56
+ }
57
+ end
58
+
59
+ describe 'integration' do
60
+ before :each do
61
+ class << self
62
+ alias_method :define_constant, :define_constants
63
+ end
64
+ end
65
+
66
+ begin
67
+ fork do
68
+ # The codeclimate-test-reporter RubyGem uses Kernel#at_exit to hook the
69
+ # end of test/spec runs for sending coverage statistics to their web
70
+ # service. We need to skip that hook in this process fork because this is
71
+ # not the end of a test/spec run, only of a process fork.
72
+ exit!(true) if ENV['CODECLIMATE_REPO_TOKEN']
73
+ end
74
+ rescue NotImplementedError => e
75
+ pending "[pending because #{e.message}]"
76
+ else
77
+ describe 'not extending a namespace' do
78
+ subject(:source_file) { 'spec/fixtures/not_autoloaded.rb' }
79
+
80
+ it { is_expected.to define_constant(:NotAutoloaded) }
81
+
82
+ it { is_expected.to define_constant('NotAutoloaded::OldSchoolAutoload') }
83
+
84
+ it { is_expected.not_to define_constant('NotAutoloaded::Nested') }
85
+
86
+ it {
87
+ is_expected.to set_up_autoload_for_constant('NotAutoloaded::OldSchoolAutoload').
88
+ from_file('fixtures/not_autoloaded/old_school_autoload')
89
+ }
90
+
91
+ it {
92
+ is_expected.not_to set_up_autoload_for_constant('NotAutoloaded::Nested')
93
+ }
94
+ end
95
+
96
+ describe 'extending a namespace whose constituent source files include' do
97
+ describe 'a conventional source filename used for autoloading' do
98
+ subject(:source_file) {
99
+ 'spec/fixtures/autoloaded_with_conventional_filename.rb'
100
+ }
101
+
102
+ it {
103
+ is_expected.to define_constant(:AutoloadedWithConventionalFilename)
104
+ }
105
+
106
+ it {
107
+ is_expected.to define_constant('AutoloadedWithConventionalFilename::OldSchoolAutoload')
108
+ }
109
+
110
+ it {
111
+ is_expected.to define_constant('AutoloadedWithConventionalFilename::Nested')
112
+ }
113
+
114
+ it {
115
+ is_expected.not_to define_constant('AutoloadedWithConventionalFilename::NONEXISTENT')
116
+ }
117
+
118
+ it {
119
+ is_expected.to set_up_autoload_for_constant('AutoloadedWithConventionalFilename::OldSchoolAutoload').
120
+ from_file('fixtures/autoloaded_with_conventional_filename/old_school_autoload')
121
+ }
122
+
123
+ it {
124
+ is_expected.to set_up_autoload_for_constant('AutoloadedWithConventionalFilename::Nested').
125
+ from_file('fixtures/autoloaded_with_conventional_filename/nested')
126
+ }
127
+
128
+ it {
129
+ is_expected.not_to set_up_autoload_for_constant('AutoloadedWithConventionalFilename::NONEXISTENT')
130
+ }
131
+ end
132
+
133
+ describe 'unconventional source filenames' do
134
+ subject(:source_file) {
135
+ 'spec/fixtures/autoloaded_with_unconventional_filename.rb'
136
+ }
137
+
138
+ it {
139
+ is_expected.to define_constant(:AutoloadedWithUnconventionalFilename)
140
+ }
141
+
142
+ it {
143
+ is_expected.to define_constant('AutoloadedWithUnconventionalFilename::OldSchoolAutoload')
144
+ }
145
+
146
+ it {
147
+ is_expected.to define_constants('AutoloadedWithUnconventionalFilename::Nested1',
148
+ 'AutoloadedWithUnconventionalFilename::Nested2')
149
+ }
150
+
151
+ it {
152
+ is_expected.to set_up_autoload_for_constant('AutoloadedWithUnconventionalFilename::OldSchoolAutoload').
153
+ from_file('fixtures/autoloaded_with_unconventional_filename/old_school_autoload')
154
+ }
155
+
156
+ it {
157
+ is_expected.to set_up_autoload_for_constant('AutoloadedWithUnconventionalFilename::Nested1').
158
+ from_file('fixtures/autoloaded_with_unconventional_filename/N-est-ed')
159
+ }
160
+
161
+ it {
162
+ is_expected.to set_up_autoload_for_constant('AutoloadedWithUnconventionalFilename::Nested2').
163
+ from_file('fixtures/autoloaded_with_unconventional_filename/N-est-ed')
164
+ }
165
+
166
+ it {
167
+ is_expected.not_to set_up_autoload_for_constant('AutoloadedWithUnconventionalFilename::NONEXISTENT')
168
+ }
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,12 @@
1
+ require 'autoloaded'
2
+
3
+ module AutoloadedWithConventionalFilename
4
+
5
+ autoload :OldSchoolAutoload,
6
+ 'fixtures/autoloaded_with_conventional_filename/old_school_autoload'
7
+
8
+ ::Autoloaded.module do |autoloaded|
9
+ autoloaded.except 'N-est-ed', 'nest_ed'
10
+ end
11
+
12
+ 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,16 @@
1
+ require 'autoloaded'
2
+
3
+ module AutoloadedWithConventionalFilename
4
+
5
+ module Nested
6
+
7
+ # module DoublyNested; end
8
+ # autoload :DoublyNested, 'somewhere/else'
9
+
10
+ ::Autoloaded.module { }
11
+
12
+ DoublyNested
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,9 @@
1
+ module AutoloadedWithConventionalFilename
2
+
3
+ module Nested
4
+
5
+ module DoublyNested; end
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,5 @@
1
+ module AutoloadedWithConventionalFilename
2
+
3
+ module OldSchoolAutoload; end
4
+
5
+ end
@@ -0,0 +1,12 @@
1
+ require 'autoloaded'
2
+
3
+ module AutoloadedWithUnconventionalFilename
4
+
5
+ autoload :OldSchoolAutoload,
6
+ 'fixtures/autoloaded_with_unconventional_filename/old_school_autoload'
7
+
8
+ ::Autoloaded.module do |autoloaded|
9
+ autoloaded.only 'N-est-ed' => [:Nested1, :Nested2]
10
+ end
11
+
12
+ end
@@ -0,0 +1,7 @@
1
+ module AutoloadedWithUnconventionalFilename
2
+
3
+ module Nested1; end
4
+
5
+ module Nested2; end
6
+
7
+ end
@@ -0,0 +1 @@
1
+ raise "The file #{__FILE__} should not have been loaded"
@@ -0,0 +1,5 @@
1
+ module AutoloadedWithUnconventionalFilename
2
+
3
+ module OldSchoolAutoload; end
4
+
5
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,5 @@
1
+ module NotAutoloaded
2
+
3
+ autoload :OldSchoolAutoload, 'fixtures/not_autoloaded/old_school_autoload'
4
+
5
+ end
@@ -0,0 +1 @@
1
+ raise "The file #{__FILE__} should not have been loaded"
@@ -0,0 +1,5 @@
1
+ module NotAutoloaded
2
+
3
+ module OldSchoolAutoload; end
4
+
5
+ end
@@ -0,0 +1,85 @@
1
+ require 'support/util'
2
+ require 'support/without_side_effects'
3
+
4
+ RSpec::Matchers.define :define_constants do |*constant_names|
5
+ match do |source_file|
6
+ # Ensure the file exists.
7
+ File.open source_file, 'r' do
8
+ end
9
+
10
+ without_side_effects do
11
+ constant_names.each do |constant_name|
12
+ if Util.constantize(constant_name)
13
+ fail "constant #{constant_name} is already defined outside #{source_file}"
14
+ end
15
+ end
16
+
17
+ load source_file
18
+
19
+ constant_names.all? do |constant_name|
20
+ Util.namespace_and_unqualified_constant_name constant_name,
21
+ raise_if_namespace_invalid: true
22
+ Util.constantize constant_name
23
+ end
24
+ end
25
+ end
26
+
27
+ description do
28
+ fragments = []
29
+ fragments << case constant_names.length
30
+ when 0
31
+ 'no constants'
32
+ when 1
33
+ "constant #{constant_names.first}"
34
+ else
35
+ "constants #{constant_names.join ' and '}"
36
+ end
37
+ "define #{fragments.join ' '}"
38
+ end
39
+ end
40
+
41
+ RSpec::Matchers.define :set_up_autoload_for_constant do |constant_name|
42
+ match do |source_file|
43
+ # Ensure the file exists.
44
+ File.open source_file, 'r' do
45
+ end
46
+
47
+ without_side_effects do
48
+ namespace, unqualified_constant_name = Util.namespace_and_unqualified_constant_name(constant_name)
49
+ if namespace && namespace.autoload?(unqualified_constant_name)
50
+ fail "#{namespace.name}::#{unqualified_constant_name} is already set up for autoload outside #{source_file}"
51
+ end
52
+
53
+ load source_file
54
+
55
+ namespace, unqualified_constant_name = Util.namespace_and_unqualified_constant_name(constant_name,
56
+ raise_if_namespace_invalid: true)
57
+ if filename_or_filenames
58
+ Array(filename_or_filenames).sort == Array(namespace.autoload?(unqualified_constant_name)).sort
59
+ else
60
+ namespace.autoload? unqualified_constant_name
61
+ end
62
+ end
63
+ end
64
+
65
+ chain :from_file do |filename|
66
+ @filename_or_filenames = filename
67
+ end
68
+
69
+ chain :from_files do |*filenames|
70
+ @filename_or_filenames = filenames
71
+ end
72
+
73
+ description do
74
+ fragments = []
75
+ fragments << "constant #{constant_name}"
76
+ if filename_or_filenames
77
+ unless (filenames = Array(filename_or_filenames)).empty?
78
+ fragments << "from file#{(filenames.length == 1) ? nil : 's'} #{filenames.join ' and '}"
79
+ end
80
+ end
81
+ "set up #{Module.name}#autoload? for #{fragments.join ' '}"
82
+ end
83
+
84
+ attr_reader :filename_or_filenames
85
+ end
@@ -0,0 +1,91 @@
1
+ require 'codeclimate-test-reporter'
2
+
3
+ CodeClimate::TestReporter.start
4
+
5
+ # This file was generated by the `rspec --init` command. Conventionally, all
6
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
7
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
8
+ # file to always be loaded, without a need to explicitly require it in any files.
9
+ #
10
+ # Given that it is always loaded, you are encouraged to keep this file as
11
+ # light-weight as possible. Requiring heavyweight dependencies from this file
12
+ # will add to the boot time of your test suite on EVERY test run, even for an
13
+ # individual file that may not need all of that loaded. Instead, consider making
14
+ # a separate helper file that requires the additional dependencies and performs
15
+ # the additional setup, and require it from the spec files that actually need it.
16
+ #
17
+ # The `.rspec` file also contains a few flags that are not defaults but that
18
+ # users commonly want.
19
+ #
20
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
+ RSpec.configure do |config|
22
+ # rspec-expectations config goes here. You can use an alternate
23
+ # assertion/expectation library such as wrong or the stdlib/minitest
24
+ # assertions if you prefer.
25
+ config.expect_with :rspec do |expectations|
26
+ # This option will default to `true` in RSpec 4. It makes the `description`
27
+ # and `failure_message` of custom matchers include text for helper methods
28
+ # defined using `chain`, e.g.:
29
+ # be_bigger_than(2).and_smaller_than(4).description
30
+ # # => "be bigger than 2 and smaller than 4"
31
+ # ...rather than:
32
+ # # => "be bigger than 2"
33
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
34
+ end
35
+
36
+ # rspec-mocks config goes here. You can use an alternate test double
37
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
38
+ config.mock_with :rspec do |mocks|
39
+ # Prevents you from mocking or stubbing a method that does not exist on
40
+ # a real object. This is generally recommended, and will default to
41
+ # `true` in RSpec 4.
42
+ mocks.verify_partial_doubles = true
43
+ end
44
+
45
+ # These two settings work together to allow you to limit a spec run
46
+ # to individual examples or groups you care about by tagging them with
47
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
48
+ # get run.
49
+ config.filter_run :focus
50
+ config.run_all_when_everything_filtered = true
51
+
52
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
53
+ # For more details, see:
54
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
55
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
56
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
57
+ config.disable_monkey_patching!
58
+
59
+ # This setting enables warnings. It's recommended, but in some cases may
60
+ # be too noisy due to issues in dependencies.
61
+ # config.warnings = true
62
+
63
+ # Many RSpec users commonly either run the entire suite or an individual
64
+ # file, and it's useful to allow more verbose output when running an
65
+ # individual spec file.
66
+ if config.files_to_run.one?
67
+ # Use the documentation formatter for detailed output,
68
+ # unless a formatter has already been configured
69
+ # (e.g. via a command-line flag).
70
+ config.default_formatter = 'doc'
71
+ end
72
+
73
+ # Print the 10 slowest examples and example groups at the
74
+ # end of the spec run, to help surface which specs are running
75
+ # particularly slow.
76
+ config.profile_examples = 1
77
+
78
+ # Run specs in random order to surface order dependencies. If you find an
79
+ # order dependency and want to debug it, you can fix the order by providing
80
+ # the seed, which is printed after each run.
81
+ # --seed 1234
82
+ config.order = :random
83
+
84
+ # Seed global randomization in this process using the `--seed` CLI option.
85
+ # Setting this allows you to use `--seed` to deterministically reproduce
86
+ # test failures related to randomization by passing the same `--seed` value
87
+ # as the one that triggered the failure.
88
+ Kernel.srand config.seed
89
+ end
90
+
91
+ require 'autoloaded'