Can't play .wav file in Rails web app: RoutingError/404 - ruby-on-rails

I'm trying to play a WAV file from my assets folder but I keep getting errors. The audio tag looks like this:
<audio src="<%= asset_path('/audios/opening.wav') %>">
Browser not compatible
</audio>
And I use a Javascript function to play it with .play(). When I test the function with a full path for WAV files that are actually hosted on the web, it works fine. It's just the one in my assets that's failing.
WAV Path:
.
├── app
│ ├── assets
│ │ ├── audios
│ │ │ └── opening.wav
Browser console error:
GET http://localhost:3000/audios/opening.wav net::ERR_ABORTED 404 (Not Found)
1 Uncaught (in promise) DOMException: Failed to load because no supported source was found.
Server error:
ActionController::RoutingError (No route matches [GET] "/audios/opening.wav"):
I'm positive that there must be a better way than creating routes for each individual audio asset, but I haven't found any solutions on here that have worked. I've seen similar questions about this using audio_path but it seems that method may have been deprecated. Appreciate any advice I can get!
Rails 7.0.3.1
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin20]

It turns out using audio_path instead of asset_path was the way to go! It wasn't working at first but worked after I added //= link_tree ../audios to the app/assets/config/manifest.js file.

Related

File locations Javascript vs Stylesheet in Rails 7

In a new default Rails 7 application using the import maps functionality, Javascript is stored in app/javascript, while CSS is located in app/assets/stylesheets. Not only are they located at different hierarchy levels, but javascript is singular, while stylesheets is plural.
I'm looking for sources that explain these divergent locations and pluralization decisions. Searches through Rails Guides and API documentation have turned up nothing, but support talk on the Rails repo suggests that docs are still being actively updated.
On the surface this seems really shortsighted, but I want to make sure I'm not missing something before I go messing with the defaults.
app/assets is used by sprockets. This is rails asset pipeline. Preprocessing, minification, compilation etc. app/assets/javascripts was a thing before javascript took over the world, and had to be given its own separate directory.
app/javascript was used by webpacker to avoid mixing it with sprockets processing. This is javascript pipeline that does what sprockets does, process, compile, minify etc. A way to bring javascript build tools into rails. Singular referring to "javascript" language not "javascripts" as in collection of js files (I guess).
Both of these directories can have css and js assets, just processed and compiled by completely different tools.
In rails 7, app/javascript is used by jsbundling-rails that comes with different js build tools, like, esbuild and webpack. After javascript is done its job, bundles go into app/assets/build where sprockets treats it as any old js or css file.
With importmaps there is really no processing but app/javascript is the logical place for it. To use importmaps, all the files in app/javascript have to be precompiled by sprockets for use in production:
// app/assets/config/manifest.js
//= ../../javascript .js
and app/javascript has to be in Rails.application.config.assets.paths:
config.assets.paths << Rails.root.join("app/javascript")
This is what importmap-rails does, among other things. In case you want to relocate anything back to app/assets.
Here is a short overview of who lives where:
app/
├─ assets/ # used by sprockets-rails, everything else hooks into it
│ ├─ build/ # compiled assets (jsbundling-rails, cssbundling-rails, tailwindcss-rails)
│ ├─ config/ # precompile `build/` if any of these three ^ are used
│ │ # or precompile `app/javascript/` if importmap-rails is used
│ ├─ stylesheets/ # used by cssbundling-rails, tailwindcss-rails
│ └─ javascripts/ # not used in rails 7, but any directory can be added to `assets/`,
│ # just add it to precompilation manifest as well https://stackoverflow.com/q/72305291/207090
└─ javascript/ # used by jsbundling-rails, importmap-rails and anything node related.
└─ controllers/ # used by stimulus-rails
Also, rails gems themselves use app/assets/javascripts to ship any js files.

Ruby on rails files setup

I have some doubts about the folders on which I should put the public files.
We got at the root path a folder called public and some other folders in app (rails 5.0.1 for me), let me show you the ones which sound strange for me:
app/assets/ (images | javascripts | stylesheets)
app/views/pages
After reading multiple tutorials and existing public projects, I saw that some people put his web template in public (js, css and images included).
Yet, in my case, because of I have seen it few times too and found it logic, I have put my template in assets separating my js, sass (in my case) files, and images in the folders already created by the RoR generator.
Additionnal, it seems logic for me to put my files in assets because my main layout gonna take my template files in assets with the framework default API. The following line works for me and gonna load my app/assets/stylesheets/ app.css.scss file
<%= stylesheet_link_tag 'app', media: 'all', 'data-turbolinks-track': 'reload' %>
Hope someone could explain what's the better way, I'm beginner with Rails, thanks.
app/assets/
This is where you put custom assets (images, js/css scripts that you own and custom to your application)
vendor/assets/
This is for third party libraries that you use in your app (carousel js plugin, etc)
.
├── app
│   ├── assets (custom assets specific to your app) 
├── public (static-files like error pages, favicon, etc which does not change much)
├── vendor
│   └── assets (third party libraries that your app uses)
Precompiled Assets
Add all the paths to your assets (images, js/css files) used in your application in assets precomile path in config/initializers/assets.rb (application.css and application.js are included by default)
All the assets when precompiled with
bundle exec rails assets:precompile
This generates public/assets directory with all the assets configured in your precompile path as readily servable static assets which are then served to your application responses.

Namespaced class on rails' app folder

I have the following folder structure:
app
├── assets
├── controllers
├── helpers
├── mailers
├── market_adapters
│   └── german.rb
│...
And the file market_adapters/german.rb is:
module MarketAdapters #(I've also tried naming it singular)
class German
end
end
When running tests I get the error:
/gems/activesupport-5.0.0/lib/active_support/dependencies.rb:512:in
`load_missing_constant': Unable to autoload constant German,
expected .../app/market_adapters/german.rb to define it (LoadError)
Adding the market_adapters folder to the autoload_paths seems to have no effect config.autoload_paths << "#{Rails.root}/app/market_adapters"
If I move the market_adapters to the lib folder, everything works. But still would like to have it under app, any ideas?
By the way, I'm using Rails 5.
All the subfolders in app are automatically auto-loaded and added to the load path. Therefore, the folder market_adapters is added to the load path, and the file called german.rb is expected to define the German class.
If you really want to use market_adapters as namespace and keep the file in app, you need to store it in the folder app/market_adapters/market_adapters/german.rb.
The right place, however, is in lib.

Custom Javascript Rails Admin

I want to add the JS from Google Analytics embed API into my rails application and only for Rails Admin (not needed anywhere else).
We have overwritten the Rails Admin Dashboard and now we are struggling with the custom JS.
I found here: https://groups.google.com/forum/#!topic/rails_admin/KgUl3gF5kTg that it needs to be placed in app/assets/javascripts/rails_admin/custom/ui.js.
So I've placed all the .js files and the .js.map files in the directory:
.
└── custom
├── active-users.js
├── chart.js
├── datepicker.js
├── moment.js
├── platform.js
├── platform.js.map
├── polymer.js
├── polymer.js.map
├── promise.js
├── ui.js
└── viewpicker.js
And I've added //= require_tree . in the ui.js file but in rails_admin I still receive:
Uncaught ReferenceError: Polymer is not defined
This means that the .JS file isn't loaded.
Thanks to this link for finding the above link: Rails Admin: add javascript library to custom action
Edit 1: Using Rails Admin in a Rails 3 env.
Edit 2:
So for testing reasons I removed all the custom JS/HTML etc.
I've set this in the ui.js:
//=require_tree .
I've set this in leecher.js:
$(document).ready(function() { document.MY_SIMPLE_VARIABLE = 2; } );
When I restart the server I go to rails admin, log out, restart the server again, log in. Go to console in chrome and type:
document.MY_SIMPLE_VARIABLE
And I receive the following:
For testing reasons I've added an:
alert("hello world");
But still no trigger.
The location of the ui.js and leecher.js is:
app/assets/javascripts/rails_admin/custom/
And this my current Gemfile:
http://pastie.org/private/zrrzjpbx5jq7enpeknsa
Edit 3:
If I put the JS code into the ui.js it shows an alert! So they are problems with the includes (//= require tree .)
Edit 4:
All the JS files I'm using: https://gist.github.com/YOUConsulting/243397c31ea28d217367
Simple example that doesn't work:
https://gist.github.com/YOUConsulting/571e785d6b6c1ed06d6b
Simple example that does work:
https://gist.github.com/YOUConsulting/52de78aa043239aae707
I've rewritten my answer to describe the complete solution in case other people need this in the future.
app/assets/javascripts/rails_admin/custom/ui.js works like a manifest file in the Rails asset pipeline, thus it supports these directives.
In order to include all .js files under custom, add
//= require_tree .
at the top of the file.
If that does not work right out of the box, running
rake tmp:clear
will solve the problem ;)
Cheers!
After talking more to Cec on this topic. He found that a simple rake tmp:clear, was the correct answer. See answer above or below.

how to handle the image location in css if using grails asset-pipeline plugin?

the jquery.flipcountdown.css file is:
.xdsoft_flipcountdown.xdsoft_size_lg >.xdsoft_digit{
width:53px;
height:76px;
background-image:url(./img/digit-lg.png);
}
the directory structure is
+flipcountdown-master
+ img
- digit-lg.png
- jquery.flipcountdown.css
the question is: how to use asset-pipeline in this case.
1: put the css under the assets/stylesheets, and put the img folder under the assets/images folder ? CAN IT WORK ?
2: put the css file and the img folder all to the assets/stylesheets folder, i am pretty sure it can work, but the asset-pipeline can gzip it?
i'm not good at js/css, and i spent much time to read the Asset-Pipeline doc and video on Youtube, but i still don't know how to use it in right way.
thx in advance
There are a few things you can do here:
If you want to utilize the organization structure provided by the asset pipeline plugin, place the .css file in assets/stylesheets directory and the image in the assets/images directory and change any references of ./img/digit-lg.png to digit-lg.png (you could also specify /assets/digit-lg.png or /assets/images/digit-lg.png and get the same result). Here's what the directory structure should look like:
├── assets
│   ├── images
│   │   ├── digit-lg.png
│   ├── javascripts
│   └── stylesheets
│   └── jquery.flipcountdown.css
The grails asset pipeline ignores the top level images, javascripts, and stylesheets folders when resolving assets, as they are purely for organization purposes.
Or, since this is a third-party stylesheet, it may be best to keep the .css file unmodified, and keep things self contained. You can just add the flipcountdown-master directory to either the assets/ directory or assets/stylesheets/, keep the css background-image url set to ./img/digit-lg.png and everything should work fine. Here's the structure in that case:
├── assets
│   ├── images
│   ├── javascripts
│   └── stylesheets
│   └── flipcountdown-master
│ └── img
│ └── digit-lg.png
│   └── jquery.flipcountdown.css
The asset pipeline is very flexible to however you feel most comfortable organizing your assets, there isn't only one way to do things. Any file that the pipeline picks up will be eligible for gzip compression.
Here is the sample app.
Particularly look at application.js and application.css where the external libraries are included.
Just clone the app from github, run-app, and hit the index page. You should see a countdown clock in the index page.

Resources