Skip to content

Commit 796fb82

Browse files
authored
Merge pull request #668 from jessecollier/jcollier/add-depend-on-directory
Adding directive depends_on_directory
2 parents fa8a968 + 55957f2 commit 796fb82

File tree

4 files changed

+113
-7
lines changed

4 files changed

+113
-7
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprocket
55
## Master
66

77
- Fix `Sprockets::Server` to return lower-cased response headers to comply with Rack::Lint 3.0. [#744](https://github.com/rails/sprockets/pull/744)
8+
- Adding new directive `depend_on_directory` [#668](https://github.com/rails/sprockets/pull/668)
9+
- Fix `application/js-sourcemap+json` charset [#669](https://github.com/rails/sprockets/pull/669)
10+
- Fix `CachedEnvironment` caching nil values [#723](https://github.com/rails/sprockets/pull/723)
811

912
## 4.0.3
1013

@@ -13,7 +16,6 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprocket
1316
- Allow assets already fingerprinted to be served through `Sprockets::Server`
1417
- Do not fingerprint files that already contain a valid digest in their name
1518
- Remove remaining support for Ruby < 2.4.[#672](https://github.com/rails/sprockets/pull/672)
16-
- Fix `CachedEnvironment` caching nil values [#723](https://github.com/rails/sprockets/pull/723)
1719

1820
## 4.0.2
1921

@@ -22,7 +24,6 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprocket
2224
## 4.0.1
2325

2426
- Fix for Ruby 2.7 keyword arguments warning in `base.rb`. [#660](https://github.com/rails/sprockets/pull/660)
25-
- Fix `application/js-sourcemap+json` charset [#669](https://github.com/rails/sprockets/pull/669)
2627
- Fix for when `x_sprockets_linecount` is missing from a source map.
2728
- Fix subresource integrity to match the digest of the asset.
2829

README.md

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ Here is a list of the available directives:
119119
- [`link_directory`](#link_directory) - Make target directory compile and be publicly available without adding contents to current
120120
- [`link_tree`](#link_tree) - Make target tree compile and be publicly available without adding contents to current
121121
- [`depend_on`](#depend_on) - Recompile current file if target has changed
122+
- [`depend_on_directory`](#depend_on_directory) - Recompile current file if any files in target directory has changed
122123
- [`stub`](#stub) - Ignore target file
123124

124125
You can see what each of these does below.
@@ -239,7 +240,7 @@ The first time this file is compiled the `application.js` output will be written
239240

240241
So, if `b.js` changes it will get recompiled. However instead of having to recompile the other files from `a.js` to `z.js` since they did not change, we can use the prior intermediary files stored in the cached values . If these files were expensive to generate, then this "partial" asset cache strategy can save a lot of time.
241242

242-
Directives such as `require`, `link`, and `depend_on` tell Sprockets what assets need to be re-compiled when a file changes. Files are considered "fresh" based on their mtime on disk and a combination of cache keys.
243+
Directives such as `require`, `link`, `depend_on`, and `depend_on_directory` tell Sprockets what assets need to be re-compiled when a file changes. Files are considered "fresh" based on their mtime on disk and a combination of cache keys.
243244

244245
On Rails you can force a "clean" install by clearing the `public/assets` and `tmp/cache/assets` directories.
245246

@@ -453,11 +454,53 @@ you need to tell sprockets that it needs to re-compile the file if `bar.data` ch
453454
var bar = '<%= File.read("bar.data") %>'
454455
```
455456

457+
To depend on an entire directory containing multiple files, use `depend_on_directory`
458+
456459
### depend_on_asset
457460

458461
`depend_on_asset` *path* works like `depend_on`, but operates
459462
recursively reading the file and following the directives found. This is automatically implied if you use `link`, so consider if it just makes sense using `link` instead of `depend_on_asset`.
460463

464+
### depend_on_directory
465+
466+
`depend_on_directory` *path* declares all files in the given *path* without
467+
including them in the bundle. This is useful when you need to expire an
468+
asset's cache in response to a change in multiple files in a single directory.
469+
470+
All paths are relative to your declaration and must begin with `./`
471+
472+
Also, your must include these directories in your [load path](guides/building_an_asset_processing_framework.md#the-load-path).
473+
474+
**Example:**
475+
476+
If we've got a directory called `data` with files `a.data` and `b.data`
477+
478+
```
479+
// ./data/a.data
480+
A
481+
```
482+
483+
```
484+
// ./data/b.data
485+
B
486+
```
487+
488+
```
489+
// ./file.js.erb
490+
//= depend_on_directory ./data
491+
var a = '<% File.read('data/a.data') %>'
492+
var b = '<% File.read('data/b.data') %>'
493+
```
494+
495+
Would produce:
496+
497+
```js
498+
var a = "A";
499+
var b = "B";
500+
```
501+
502+
You can also see [Index files are proxies for folders](#index-files-are-proxies-for-folders) for another method of organizing folders that will give you more control.
503+
461504
### stub
462505

463506
`stub` *path* excludes that asset and its dependencies from the asset bundle.
@@ -499,9 +542,9 @@ When you modify the `logo.png` on disk, it will force `application.css` to be
499542
recompiled so that the fingerprint will be correct in the generated asset.
500543

501544
You can manually make sprockets depend on any other file that is generated
502-
by sprockets by using the `depend_on` directive. Rails implements the above
503-
feature by auto calling `depend_on` on the original asset when the `asset_url`
504-
is used inside of an asset.
545+
by sprockets by using the `depend_on` or `depend_on_directory` directive. Rails
546+
implements the above feature by auto calling `depend_on` on the original asset
547+
when the `asset_url` is used inside of an asset.
505548

506549
### Styling with Sass and SCSS
507550

lib/sprockets/directive_processor.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,24 @@ def process_depend_on_asset_directive(path)
285285
to_load(resolve(path))
286286
end
287287

288+
# Allows you to state a dependency on a relative directory
289+
# without including it.
290+
#
291+
# This is used for caching purposes. Any changes made to
292+
# the dependency directory will invalidate the cache of the
293+
# source file.
294+
#
295+
# This is useful if you are using ERB and File.read to pull
296+
# in contents from multiple files in a directory.
297+
#
298+
# //= depend_on_directory ./data
299+
#
300+
def process_depend_on_directory_directive(path = ".", accept = nil)
301+
path = expand_relative_dirname(:depend_on_directory, path)
302+
accept = expand_accept_shorthand(accept)
303+
resolve_paths(*@environment.stat_directory_with_dependencies(path), accept: accept)
304+
end
305+
288306
# Allows dependency to be excluded from the asset bundle.
289307
#
290308
# The `path` must be a valid asset and may or may not already
@@ -374,7 +392,7 @@ def resolve_paths(paths, deps, **kargs)
374392
next if subpath == @filename || stat.directory?
375393
uri, deps = @environment.resolve(subpath, **kargs)
376394
@dependencies.merge(deps)
377-
yield uri if uri
395+
yield uri if uri && block_given?
378396
end
379397
end
380398

test/test_asset.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,50 @@ def self.test(name, &block)
123123
end
124124
end
125125
end
126+
127+
test "modify asset's dependency file in directory" do
128+
main = fixture_path('asset/test-main.js.erb')
129+
dep = fixture_path('asset/data/foo.txt')
130+
begin
131+
::FileUtils.mkdir File.dirname(dep)
132+
sandbox main, dep do
133+
write(main, "//= depend_on_directory ./data\n<%= File.read('#{dep}') %>")
134+
write(dep, "a;")
135+
asset = asset('test-main.js')
136+
old_digest = asset.hexdigest
137+
old_uri = asset.uri
138+
assert_equal "a;\n", asset.to_s
139+
140+
write(dep, "b;")
141+
asset = asset('test-main.js')
142+
refute_equal old_digest, asset.hexdigest
143+
refute_equal old_uri, asset.uri
144+
assert_equal "b;\n", asset.to_s
145+
end
146+
ensure
147+
::FileUtils.rmtree File.dirname(dep)
148+
end
149+
end
150+
151+
test "asset's dependency on directory exists" do
152+
main = fixture_path('asset/test-missing-directory.js.erb')
153+
dep = fixture_path('asset/data/foo.txt')
154+
155+
begin
156+
sandbox main, dep do
157+
::FileUtils.rmtree File.dirname(dep)
158+
write(main, "//= depend_on_directory ./data")
159+
assert_raises(Sprockets::ArgumentError) do
160+
asset('test-missing-directory.js')
161+
end
162+
163+
::FileUtils.mkdir File.dirname(dep)
164+
assert asset('test-missing-directory.js')
165+
end
166+
ensure
167+
::FileUtils.rmtree File.dirname(dep)
168+
end
169+
end
126170
end
127171

128172
class TextStaticAssetTest < Sprockets::TestCase

0 commit comments

Comments
 (0)