如何在js.erb文件中通过asset_path动态设置图片路径?
I’ve run into this exact issue before with Rails’ asset pipeline and JS.erb files—let me break down why your current approach isn’t working and how to fix it properly:
Your line imgObj.src = "<%= asset_path("+ path +") %>"; fails because Rails processes ERB templates on the server side before sending JavaScript to the client. When the server runs asset_path, the client-side variable path doesn’t exist yet—so it’s just passing the literal string "+ path +" instead of your actual image filename.
Here are three practical solutions, tailored to different use cases:
1. Predefine a Path Mapping (Best for Small, Known Image Sets)
If you have a fixed list of images you’ll use, create a JavaScript object in your .js.erb that maps filenames to their fingerprinted asset paths. This lets you safely reference paths client-side:
// my.js.erb // Define all image paths server-side first const imagePathMap = { 'image1.png': '<%= asset_path("image1.png") %>', 'image2.png': '<%= asset_path("image2.png") %>', // Add any other required images here }; // Use the map in your client-side logic var path = element.image_path; var imgObj = new Image(); imgObj.src = imagePathMap[path];
2. Use a Base Asset Path (Great for Images in a Single Directory)
If all your dynamic images live in a subdirectory like app/assets/images/dynamic/, grab the base path for that directory via asset_path, then append your filename client-side:
// my.js.erb // Get the server-generated base path for your image directory const dynamicImagesBasePath = '<%= asset_path("dynamic/") %>'; // Append your client-side filename to the base path var path = element.image_path; var imgObj = new Image(); imgObj.src = dynamicImagesBasePath + path;
Note: Ensure your filenames match exactly what’s in the asset pipeline—Rails handles fingerprinting for the base path, so appending the correct filename will point to the right asset.
3. Auto-Generate the Path Map (For Large/Variable Image Sets)
If you have lots of images or don’t want to list them manually, use Ruby to scan your assets directory and generate the path map automatically:
// my.js.erb // Auto-generate a map of all PNG images in app/assets/images/ const imagePathMap = <%= Dir.glob(Rails.root.join('app', 'assets', 'images', '*.png')).each_with_object({}) do |file, hash| filename = File.basename(file) hash[filename] = asset_path(filename) end.to_json %>; // Use the auto-generated map as before var path = element.image_path; var imgObj = new Image(); imgObj.src = imagePathMap[path];
Swap *.png with *.jpg, *.svg, or another extension to match your image types.
All these methods properly leverage the Rails asset pipeline, ensuring you get the fingerprinted paths required for production while keeping your client-side code dynamic.
内容的提问来源于stack exchange,提问作者Sam

