Skip to content

Instantly share code, notes, and snippets.

@joelmoss
Last active April 15, 2021 23:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joelmoss/7aeb5823ee07bbaf26ef64031f9a8a91 to your computer and use it in GitHub Desktop.
Save joelmoss/7aeb5823ee07bbaf26ef64031f9a8a91 to your computer and use it in GitHub Desktop.
Include JS/CSS assets from anywhere in your Rails application - even outside /app/assets
module AssetsAnywhere
class Middleware
def initialize(app)
@app = app
@builder = Builder.new
end
def call(env)
@builder.attempt(env) || @app.call(env)
end
end
class Builder
ASSET_TYPES = /\.(js|css)$/i
def initialize
@file_server = Rack::Files.new(Rails.root)
end
def attempt(env)
request = Rack::Request.new(env)
(request.get? || request.head?) && serve(request)
end
private
def serve(request)
return unless ASSET_TYPES.match?(request.path_info)
file_readable?(request.path_info) && @file_server.call(request.env)
end
def clean_path(path_info)
path = Rack::Utils.unescape_path path_info.chomp('/').delete_prefix('/')
Rack::Utils.clean_path_info path if Rack::Utils.valid_path? path
end
def file_readable?(path)
return unless (path = clean_path(path))
file_stat = File.stat(Rails.root.join(path.delete_prefix('/').b).to_s)
rescue SystemCallError
false
else
file_stat.file? && file_stat.readable?
end
end
end
Rails.application.config.middleware.insert_after ActionDispatch::Static, AssetsAnywhere::Middleware
<%# In your views you can do... %>
<%= javascript_include_tag '/lib/some_javascript.js' %>
<%= javascript_include_tag '/app/models/user.js' %>
<%= stylesheet_link_tag '/app/views/layouts/application.css' %>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment