15

So I have been using rails for quite a while. But with Rails 6 I have been really struggling to get moving. I have some custom gems I use for assets and things and I cannot figure out how to load the js files.

What I am used to

application.js

//= require activestorage
//= require jquery-3.3.1.min
//= require popper.min
//= require bootstrap
//= require mdb
//= require wysiwyg
//= require addons/pickr.min
//= require modules/buttons
//= require modules/cards
//= require modules/waves
//= require activestorage
//= require turbolinks
//= require_tree .

But this does not load in Rails 6 with Webpacker. I was unable to find a basic solution online for this that did not involve adding multiple js files and lines of code to the app to patch a solution together. What I did try was

app/javascript/packs/application.js

require("@rails/ujs").start()
require("turbolinks").start()
require ("jquery-3.3.1.min").start()
require ("popper.min").start()
require ("bootstrap").start()
require ("mdb").start()
require ("wysiwyg").start()
require ("addons/pickr.min").start()
require ("modules/buttons").start()
require ("modules/cards").start()
require ("modules/waves").start()
require("@rails/activestorage").start()
require("channels")

The assets are in the correct place inside the gem (so the first version in a rails 5 app does load everything as expected). I can add some of these with yarn, but I want to use the actual files from the gem, not just get bootstrap working, is there a straightforward solution to this? I also tried adjusting the path in the require but that did not work either.

Thanks for any help!

Rockwell Rice
  • 3,541
  • 4
  • 28
  • 48
  • What's the location of the JavaScript files in question? I'm assuming the first snippet to be in `app/assets/javascripts/application.js` while the second is in `app/javascript/packs/application.js` Am I correct assuming this? – 3limin4t0r Sep 09 '19 at 19:41
  • Yes, that is the location of the snippets, sorry I should have marked that. The js files to be included are in a gem and the location would be in `/vendor/assets/javascripts/*` – Rockwell Rice Sep 09 '19 at 20:42

4 Answers4

3

You need to import js files via gem. Maybe this can help you:

import jQuery from 'jquery'

<%= File.read(File.join(Gem.loaded_specs['bla_bla_gem'].full_gem_path, 'lib', 'assets', 'javascripts', 'bla_bla.js')) %>

Related issue comment

demir
  • 3,936
  • 2
  • 15
  • 27
1

So to answer in rails 6 you will notice the use of the javascript folder app/javascript this means that anything you do with JS should be done from there. The reliance on gems for these is now minimal and replaced by yarn.

I will give you an example of my process for using js libraries. for the example i will call bootstrap using yarn. I have included the custom files to help you call each library.

this is a process I like to use which I have modified from something i read on medium a while back

# app/javascript/packs/application.js
import '../stylesheets/application'


# app/views/layouts/application.html.erb
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
in the console run

yarn add bootstrap@4.3.1 jquery popper.js

then

# config/webpack/environment.js
...
const webpack = require('webpack')
environment.plugins.append(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    Popper: ['popper.js', 'default']
  })
)

... then

# app/javascript/packs/bootstrap_custom.js
import 'bootstrap/js/dist/alert'
import 'bootstrap/js/dist/button'
import 'bootstrap/js/dist/carousel'
import 'bootstrap/js/dist/collapse'
import 'bootstrap/js/dist/dropdown'
import 'bootstrap/js/dist/index'
import 'bootstrap/js/dist/modal'
import 'bootstrap/js/dist/popover'
import 'bootstrap/js/dist/scrollspy'
import 'bootstrap/js/dist/tab'
import 'bootstrap/js/dist/toast'
import 'bootstrap/js/dist/tooltip'
import 'bootstrap/js/dist/util'

And link it in your app/javascript/packs/application.js file.

# app/javascript/packs/application.js
import './bootstrap_custom.js'
then

# app/javascript/stylesheets/application.scss
@import './bootstrap_custom.scss'
then

# app/javascript/stylesheets/bootstrap_custom.scss
@import '~bootstrap/scss/_functions.scss';
@import '~bootstrap/scss/_variables.scss';
@import '~bootstrap/scss/_mixins.scss';
@import '~bootstrap/scss/_root.scss';
@import '~bootstrap/scss/_reboot.scss';
@import '~bootstrap/scss/_type.scss';
@import '~bootstrap/scss/_alert.scss';
@import '~bootstrap/scss/_badge';
@import '~bootstrap/scss/_breadcrumb';
@import '~bootstrap/scss/_button-group';
@import '~bootstrap/scss/_buttons';
@import '~bootstrap/scss/_buttons.scss';
@import '~bootstrap/scss/_card.scss';
@import '~bootstrap/scss/_carousel.scss';
@import '~bootstrap/scss/_close.scss';
@import '~bootstrap/scss/_code.scss';
@import '~bootstrap/scss/_custom-forms.scss';
@import '~bootstrap/scss/_dropdown.scss';
@import '~bootstrap/scss/_forms.scss';
@import '~bootstrap/scss/_grid.scss';
@import '~bootstrap/scss/_images.scss';
@import '~bootstrap/scss/_input-group.scss';
@import '~bootstrap/scss/_jumbotron.scss';
@import '~bootstrap/scss/_list-group.scss';
@import '~bootstrap/scss/_media.scss';
@import '~bootstrap/scss/_modal.scss';
@import '~bootstrap/scss/_nav.scss';
@import '~bootstrap/scss/_navbar.scss';
@import '~bootstrap/scss/_pagination.scss';
@import '~bootstrap/scss/_popover.scss';
@import '~bootstrap/scss/_print.scss';
@import '~bootstrap/scss/_progress.scss';
@import '~bootstrap/scss/_spinners.scss';
@import '~bootstrap/scss/_tables.scss';
@import '~bootstrap/scss/_toasts.scss';
@import '~bootstrap/scss/_tooltip.scss';
@import '~bootstrap/scss/_transitions.scss';
@import '~bootstrap/scss/_utilities.scss';

If you choose to follow this follow it precisely, do not change the scss lines etc it will mess it up

Jem Built
  • 824
  • 6
  • 18
  • Right, so the question is how to load this in from a gem. Your answer seems to basically say convert your gem to something you can install with yarn, correct? – Rockwell Rice Sep 10 '19 at 16:24
  • 1
    My answer says that the asset pipeline for js libraries is treated differently in rails 6, hence the addition of the node-modules folder and the stylesheet_pack_tag javascript_pack_tag. I am no expert, but this is what worked for me... and I think it makes it a lot more robust to implement JS in a project. If you want to use the gem, just dont include the pack_tag for js, go back to the old tag – Jem Built Sep 10 '19 at 20:25
1

You'll need to get them directly from the gem files.

Change your application.js to application.js.erb and follow demir solution. You can also use the next to import more than one file.

<% ['file_1', 'file_2'].each do |file| %>
 import "<%= File.join(Gem.loaded_specs['my_gem'].full_gem_path, 'app', 'assets', 'javascripts', file) %>";
<% end %>
Gerardo S
  • 138
  • 8
  • Install webpacker support for `js.erb` files using `bin/bundle exec rails webpacker:install:erb` see https://stackoverflow.com/a/64964126/960184 – Richard Logwood Mar 13 '21 at 19:48
  • 1
    One gotcha is that changes to the files in the gem directory don't seem to automatically invoke `bin/webpack` rebuiild; as a change `javascript/packs/application.js.erb` would. When changing a file in the gem directory you'll have to manually rebuild the javascript packs with the command `bin/webpack`. Found this out while debugging a gem and changing it's javascript. Of course those changes in a gem file will get wiped out on deploy, but it's nice to have the flexibility to hack the code there while debugging. – Richard Logwood Mar 14 '21 at 16:25
-4

I think the location of file may be creating an issue for your case: File should be in app/assets/javascripts/application.js while the your file is in app/javascript/packs/application.js

Hope this will help you.