ruby-on-railswebpackbabeljswebpackerexecjs

Call Javascript from Rails 6 Service Object


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?


Solution

  • 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);
    });