truck 0.8.0 → 0.8.1

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
  SHA1:
3
- metadata.gz: c8475ef41616dc1d5e77921e3c1a4a1c2f49e4ee
4
- data.tar.gz: 690aa4f1b04fcbb4df44fc03da487edf43c10171
3
+ metadata.gz: b9163ddda9ad94d4bdb3142fde6704ac24c8fe2e
4
+ data.tar.gz: 377e00cc27d4b0f6ea8ef1b0d3386c7ca7e9cc43
5
5
  SHA512:
6
- metadata.gz: 24820f2e0c852256e6f66316070067444de7a27d7819265219840b55a898b911a2979a756b887d10125047db779d4f2224b41f04b7291b0b8762950d5007f11d
7
- data.tar.gz: 3925f6a1600e036edb2cdbda4621dc6aef8a937b79d03bfe37bf5ae37510cafdb4223c7bda5d877d45a3427f2a1ea0dc1694a7ed53dd2efa062171f306f83792
6
+ metadata.gz: a55de745877a006ec2722fb2c68741b6b41eb4f673122a42f6d457a42d2a6a8a4bca5640d487ef58c52ca22003a0745859c75e821611cde4ef7f7e22d0894611
7
+ data.tar.gz: fd4ff258f9782f0ef11f665d0125fbac6ada1ef10f54286f87cfd39aa64d3b383a1e28cf99afd160f92bc21174991fbed12ddfd8bcbbf258a3a4503723851475
data/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # Truck
2
2
 
3
- Truck is an alternative autoloader that doesn't pollute the global namespace. Specifically, it does not load constants into `Object`; rather, it loads them into *Contexts* that you define. This has two main advantages:
3
+ Truck is an alternative autoloader that doesn't pollute the global namespace. Specifically, it does not load constants into `Object`; rather, it loads them into *Contexts* that you define. This has three main advantages:
4
4
 
5
5
  1. `reload!` is very fast; `Object.send(:remove_const, :MyContext)` does the trick
6
6
  2. You can have multiple autoloaders running in parallel contexts
7
+ 3. Eliminates the need for `fork()` based preloaders like `zeus` and `spring`. Instead, load your gems, define your contexts, and safely `reload!` them between each test run.
8
+
7
9
 
8
10
  ## Installation
9
11
 
@@ -23,15 +25,21 @@ Or install it yourself as:
23
25
 
24
26
  Unlike ActiveSupport's autoloader, truck requires a bit of setup for each context. An example:
25
27
 
26
- Truck.define_context :MyContext, root: "/path/to/context/root"
28
+ ```ruby
29
+ Truck.define_context :MyContext, root: "/path/to/context/root"
30
+ ```
27
31
 
28
32
  Also, after defining all your contexts, you'll want to boot everyone up:
29
33
 
30
- Truck.boot!
34
+ ```ruby
35
+ Truck.boot!
36
+ ```
31
37
 
32
38
  You'll want to define all your contexts, then fork/spawn threads, then have every sub process invoke `Truck.boot!` separately.
33
39
 
34
- There is no notion of autoload paths; if you want multiple autoload paths, you'd define multiple contexts. In this example, a top level module called `MyContext` would get defined. Suppose you had a class called `Foo` living in `/path/to/context/root/foo.rb`:
40
+ ### Referencing constants
41
+
42
+ Suppose you had a class called `Foo` living in `/path/to/context/root/foo.rb`:
35
43
 
36
44
  ```ruby
37
45
  # /path/to/context/root/foo.rb
@@ -53,25 +61,49 @@ end
53
61
 
54
62
  `Foo` can reference `Bar` without an explicit require. So how does the world outside of `MyContext` reference objects?
55
63
 
56
- MyContext.resolve_const("Bar")
64
+ ```ruby
65
+ MyContext.resolve_const("Bar")
66
+ ```
57
67
 
58
68
  This works with namespaced constant names, too:
59
69
 
60
- MyContext.resolve_const("Foo::Bar::Baz")
70
+ ```ruby
71
+ MyContext.resolve_const("Foo::Bar::Baz")
72
+ ```
73
+
74
+ ### Other
61
75
 
62
76
  `MyContext` has some other interesting methods on it:
63
77
 
64
- # Wipe the whole context and reload it (also aliased as reload!)
65
- MyContext.reset!
78
+ ```ruby
79
+ # Wipe the whole context and reload it (also aliased as reload!)
80
+ MyContext.reset!
66
81
 
67
- # Kill the context
68
- MyContext.shutdown!
82
+ # Kill the context
83
+ MyContext.shutdown!
69
84
 
70
- # Eagerly load the entire context into memory (good for production)
71
- MyContext.eager_load!
85
+ # Eagerly load the entire context into memory (good for production)
86
+ MyContext.eager_load!
87
+ ```
72
88
 
73
89
  These methods are also of course on `Truck` as well, and invoke the same operations on every context.
74
90
 
91
+ ### Autoload Paths
92
+
93
+ By default, the `root` you pass to the `Context` is your autoload paths. You can alternatively supply a list of autoload paths relative to `root`:
94
+
95
+ ```ruby
96
+ Truck.define_context(
97
+ :MyContext,
98
+ root: "/path/to/context/root",
99
+ autoload_paths: %w(app/models app/controllers lib)
100
+ )
101
+ ```
102
+
103
+ ### Compatibiilty
104
+
105
+ Currently, truck has been tested against 2.1.1. It uses refinements internally. The plan is to support recent rubinius releases as well.
106
+
75
107
  ## Contributing
76
108
 
77
109
  1. Fork it ( https://github.com/ntl/truck/fork )
data/lib/truck.rb CHANGED
@@ -36,3 +36,7 @@ module Truck
36
36
  contexts.each_value.select(&:booted?).each(&block)
37
37
  end
38
38
  end
39
+
40
+ # Load this last so that when truck itself has unresolvable constants, we throw
41
+ # up vanilla ruby NameErrors.
42
+ require_relative "truck/core_ext"
@@ -113,19 +113,3 @@ module Truck
113
113
  end
114
114
  end
115
115
  end
116
-
117
- class Module
118
- def const_missing(const)
119
- catch :const do
120
- Truck::Autoloader.handle const, from: self
121
- end
122
- rescue NameError => name_error
123
- if name_error.class == NameError
124
- # Reraise the error to keep our junk out of the backtrace
125
- raise NameError, name_error.message
126
- else
127
- # NoMethodError inherits from NameError
128
- raise name_error
129
- end
130
- end
131
- end
@@ -3,32 +3,23 @@ module Truck
3
3
 
4
4
  class Context
5
5
  class ConstResolver
6
- attr :current_path, :autoload_paths, :context, :expanded_const
6
+ attr :current_path, :context, :expanded_const
7
7
 
8
- def initialize(context:, expanded_const:, autoload_paths: [''])
9
- @autoload_paths = autoload_paths
8
+ def initialize(context:, expanded_const:)
10
9
  @context = context
11
10
  @expanded_const = expanded_const
12
11
  end
13
12
 
14
- def autoload_paths=(paths)
15
- autoload_paths.clear
16
- autoload_paths.concat paths
17
- end
18
-
19
- def const_get
20
- walk_const_parts.reduce context.mod do |mod, const_part|
21
- return nil unless mod.const_defined?(const_part)
22
- mod.const_get const_part
23
- end
13
+ def resolve
14
+ check_already_loaded or resolve!
24
15
  end
25
16
 
26
- def each_autoload_path
27
- autoload_paths.each do |autoload_path|
28
- @current_path = context.root.join autoload_path
29
- yield
17
+ def resolve!
18
+ each_possible_rb_file do |rb_file|
19
+ context.load_file rb_file
20
+ check_loaded rb_file
30
21
  end
31
- @current_path = nil
22
+ const_get
32
23
  end
33
24
 
34
25
  def each_possible_rb_file
@@ -40,6 +31,14 @@ module Truck
40
31
  end
41
32
  end
42
33
 
34
+ def each_autoload_path
35
+ context.autoload_paths.each do |autoload_path|
36
+ @current_path = autoload_path
37
+ yield
38
+ end
39
+ @current_path = nil
40
+ end
41
+
43
42
  def each_rb_file_from_base_path(base_path)
44
43
  base_path.ascend do |path|
45
44
  return if path == context.root
@@ -48,16 +47,11 @@ module Truck
48
47
  end
49
48
  end
50
49
 
51
- def resolve
52
- check_already_loaded or resolve!
53
- end
54
-
55
- def resolve!
56
- each_possible_rb_file do |rb_file|
57
- context.load_file rb_file
58
- check_loaded rb_file
50
+ def const_get
51
+ walk_const_parts.reduce context.mod do |mod, const_part|
52
+ return nil unless mod.const_defined?(const_part)
53
+ mod.const_get const_part
59
54
  end
60
- const_get
61
55
  end
62
56
 
63
57
  def walk_const_parts(const = expanded_const)
data/lib/truck/context.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  module Truck
2
2
  class Context
3
- attr :mod, :name, :root
3
+ attr :autoload_paths, :mod, :name, :root
4
4
 
5
- def initialize(name, parent: nil, root:)
5
+ def initialize(name, parent: nil, root:, autoload_paths: ['.'])
6
6
  @mod = build_mod
7
7
  @name = name
8
8
  @root = Pathname(root) if root
9
9
  @parent = parent
10
+ @autoload_paths = expand_autoload_paths autoload_paths
10
11
  end
11
12
 
12
13
  class << self
@@ -67,6 +68,10 @@ module Truck
67
68
  Module.new
68
69
  end
69
70
 
71
+ def expand_autoload_paths(paths)
72
+ paths.map do |path| root.join path; end
73
+ end
74
+
70
75
  end
71
76
 
72
77
  class AutoloadError < NameError
@@ -0,0 +1,15 @@
1
+ class Module
2
+ def const_missing(const)
3
+ catch :const do
4
+ Truck::Autoloader.handle const, from: self
5
+ end
6
+ rescue NameError => name_error
7
+ if name_error.class == NameError
8
+ # Reraise the error to keep our junk out of the backtrace
9
+ raise NameError, name_error.message
10
+ else
11
+ # NoMethodError inherits from NameError
12
+ raise name_error
13
+ end
14
+ end
15
+ end
data/lib/truck/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Truck
2
- VERSION = "0.8.0"
2
+ VERSION = "0.8.1"
3
3
  end
@@ -36,4 +36,8 @@ class AutoloadingTest < Minitest::Test
36
36
  end
37
37
  assert_equal "uninitialized constant Abracadabra", exception.message
38
38
  end
39
+
40
+ def test_explicit_autoload_paths
41
+ assert_equal 'hello from Bar::Z', MultipleAutoloadPaths::A.references_z
42
+ end
39
43
  end
@@ -55,6 +55,10 @@ module A
55
55
  C::CA::CAA::CAAA.message
56
56
  end
57
57
 
58
+ def self.references_z
59
+ Z.message
60
+ end
61
+
58
62
  module AB
59
63
  def self.message
60
64
  "hello from A::AB"
@@ -153,6 +157,14 @@ module B
153
157
  end
154
158
  FILE
155
159
 
160
+ File.write "/bar/z.rb", <<-FILE
161
+ module Z
162
+ def self.message
163
+ "hello from Bar::Z"
164
+ end
165
+ end
166
+ FILE
167
+
156
168
  Dir.mkdir "/my_app"
157
169
  Dir.mkdir "/my_app/lib"
158
170
  File.write "/my_app/lib/a.rb", <<-FILE
@@ -2,6 +2,7 @@ module TestsAutoloading
2
2
  def setup
3
3
  @foo = Truck.define_context :Foo, root: "/foo"
4
4
  @bar = Truck.define_context :Bar, root: '/bar', parent: :Foo
5
+ @multi = Truck.define_context :MultipleAutoloadPaths, root: "/", autoload_paths: %w(foo bar)
5
6
  Truck.boot!
6
7
  assert_nil Truck::Autoloader.current_autoloader
7
8
  end
@@ -76,6 +76,23 @@ class ContextTest < Minitest::Test
76
76
  refute @context.booted?
77
77
  end
78
78
 
79
+ def test_autoload_path_defaults_to_root
80
+ assert_equal %w(/foo), Truck.contexts.fetch(:Foo).autoload_paths.map(&:to_s)
81
+ end
82
+
83
+ def test_explicit_autoload_paths
84
+ context = Truck.define_context :MultipleAutoloadPaths, root: "/", autoload_paths: %w(foo bar)
85
+ context.boot!
86
+
87
+ mod = context.resolve_const('A')
88
+ assert_kind_of Module, mod
89
+ assert_equal 'MultipleAutoloadPaths::A', mod.name
90
+
91
+ mod = context.resolve_const('B::BA')
92
+ assert_kind_of Module, mod
93
+ assert_equal 'MultipleAutoloadPaths::B::BA', mod.name
94
+ end
95
+
79
96
  private
80
97
 
81
98
  def assert_autoloaded_module(expected_name, mod)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: truck
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ntl
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-05 00:00:00.000000000 Z
11
+ date: 2014-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -96,6 +96,7 @@ files:
96
96
  - lib/truck/autoloader.rb
97
97
  - lib/truck/const_resolver.rb
98
98
  - lib/truck/context.rb
99
+ - lib/truck/core_ext.rb
99
100
  - lib/truck/string_inflections.rb
100
101
  - lib/truck/version.rb
101
102
  - test/integration/autoloading_test.rb