1

I'd like to call a Javascript library from a Service Object.

I have the following Javascript in /app/javascript/packs/readability.js.

import Readability from '@mozilla/readability';

function articleBody(document) {
  var article = new Readability(document).parse();
  return article.content;
}

I found that webpacker-ed files are avaliable via asset_pack_path for use in Views. I tried adding this to my Service Object, as shown below (using the therubyracer gem).

(I tried using ExecJS, which seems to be much more popular than therubyracer, but even using an unprocessed file with ES5 Javascript, it only returned errors.)

cxt = V8::Context.new
cxt.load(ActionController::Base.helpers.asset_pack_path 'readability.js')
puts cxt.eval("articleBody('http://example.com/')")

This is returning No such file or directory @ rb_sysopen - /packs/js/readability-20f57636.js.

localhost:3000/packs/js/readability-20f57636.js loads fine in the browser.

How can I load a webpacker processed file in a Service Object?

Brad West
  • 943
  • 7
  • 19

2 Answers2

0

The error is saying it can't find the file, it looks like you are saving it in /javascript but webpacker is looking in js. Ensure you have this line in your webpacker.yml:

default: &default
   source_path: app/javascript

Instead of:

default: &default
   source_path: app/js
kykyi
  • 375
  • 4
  • 10
  • In my webpacker.yml file I have it as you suggest: `source_path: app/javascript`. I guess the compilation gets sent to /js? – Brad West Feb 11 '21 at 13:08
  • Interesting, could you post the ```webpacker.yml```? – kykyi Feb 11 '21 at 13:20
  • Added to question. – Brad West Feb 11 '21 at 13:33
  • Why dont you try adding a ```js``` folder and placing it in there? – kykyi Feb 12 '21 at 13:04
  • How would I know what Webpacker is going to call the file? These processed files aren't committed to the repo by convention so the production server would be likely to name the file something different. I'm starting to think this isn't the way this should be done. Perhaps there is a different/better way to use Babel compiled Javascript when it's not used in a View? – Brad West Feb 12 '21 at 13:29
0

You don't need to compile or transpile the Javascript if it's not running in the browser. You can send the data from Rails to Node by executing a shell script from Ruby.

In the Service Object (or Controller):

require "open3"
output, status = Open3.capture2("node ./lib/test.js", stdin_data: document)
# The `output` variable above will be returned with the content of `data` from the below script.
puts output

Script in /lib or /bin:

const fs = require('fs');

fs.readFile(0, 'utf8', function(err, data) {
  if (err) throw err;
  // do your proccessing here...
  console.log(data);
});
Brad West
  • 943
  • 7
  • 19