![Page 1: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/1.jpg)
Reusing your frontend JS on the server with V8/RhinoPushing SRP & DI/IoC to whole new level
![Page 2: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/2.jpg)
Kenneth Kalmer
Chief Rocket Scientist @ ValuationUP.com
@kennethkalmer
github/kennethkalmer
www.opensourcery.co.za
kennethkalmer
![Page 3: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/3.jpg)
ValuationUP.com
Help entrepreneurs make REAL sense of their management accounts
Comparative analysis within industry
Refactoring financials by getting from red to green
Take actions to increase their valuations
Valuation is the ultimate metric
![Page 4: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/4.jpg)
The challenge
We need a very responsive UI
Realtime updates as the user inputs information
The RTT to the server is not worth the wait for such a simple formula
![Page 5: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/5.jpg)
![Page 6: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/6.jpg)
Done!
Repeat that for 50+ financial models
Build fully buzzword compliant frontend
![Page 7: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/7.jpg)
Panic!
Let’s offer a PDF with all the information
A PDF...
...WITH ALL THE INFORMATION
![Page 8: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/8.jpg)
![Page 9: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/9.jpg)
We did it!But how?
![Page 10: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/10.jpg)
Dilemma
Duplicate?
Reuse?
wkhtmltopdf? (a.k.a. wtftopdf)
![Page 11: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/11.jpg)
Reuse!
Single Responsibility Principle
Dependency Injection/Inversion on Control
Use as much JS on the server as possible, where possible!
![Page 12: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/12.jpg)
By usingtherubyracer (github.com/cowboyd/rubyracer)
therubyrhino (github.com/cowboyd/rubyrhino)
coffee-script
1 gem 'therubyracer', platforms: :ruby2 gem 'therubyrhino', platforms: :jruby3 4 gem 'coffee-script'
![Page 13: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/13.jpg)
That’s WACC!
![Page 14: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/14.jpg)
With coffee 1 # Determine the WACC of the business (weighted average cost of capital) 2 class Demo.WACC 3 4 constructor: (statement) -> 5 @statement = statement 6 7 @cost_of_equity = statement.cost_of_equity 8 unless _.isFinite( @cost_of_equity ) 9 @cost_of_equity = 0.3010 11 calculate: ->12 13 e = ( @statement.equity / ( @statement.debt + @statement.equity ) ) * @cost_of_equity14 d = ( @statement.debt / ( @statement.debt + @statement.equity ) ) * @statement.costOfDebt15 t = ( 1 - @statement.taxRate )16 17 e + d * t18 19 # Return the calculated WACC20 value: ->21 @wacc or= @calculate()
![Page 15: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/15.jpg)
Present it
1 class Demo.WaccLayout 2 3 # The view that will render our information 4 view: null 5 6 initialize: (data, view = null) -> 7 @data = data 8 @view = view 9 10 render: ->11 wacc = new Demo.WACC( @data.statement )12 13 @view.render( wacc: wacc.value() )
![Page 16: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/16.jpg)
Client-side view & usage 1 # Simple backbone view 2 class Demo.WaccView extends Backbone.View 3 4 render: (options) -> 5 wacc = options.wacc 6 7 @$el.empty().append( "<h1>#{wacc}</h1>" ) 8 9 10 11 12 13 # Initialize a view14 view = new Demo.WaccView( el: '#wacc' )15 16 # Load and render our layout17 layout = new Demo.WaccLayout( view: view, data: data )18 layout.render()
![Page 17: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/17.jpg)
Reuse on the server...
![Page 18: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/18.jpg)
JavaScript Context 1 require 'v8' 2 # require 'rhino' 3 4 # This service wraps a JS context and allows us to interact with our Javascript 5 # directly in Ruby. 6 class Javascript 7 8 # Our V8 context object 9 attr_reader :context10 11 # Some delegations12 delegate :load, :eval, :[], :[]=, to: :context13 14 def initialize()15 @context = V8::Context.new16 #@context = Rhino::Context.new17 18 # Setup a fake 'window' object19 @context['window'] = FakeWindow.new( @context )20 @context['console'] = FakeConsole.new21 22 # Load our global setup23 load_coffee Rails.root.join( 'app/assets/javascripts/setup.js.coffee' )24 end25 26 # truncated, lots more detracting stuff down below...27 28 end
![Page 19: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/19.jpg)
CoffeeScript sprinkles
1 # Compile and load a CoffeeScript file into the current context2 def load_coffee( path )3 compiled_coffeescript = CoffeeScript.compile( File.read( path ) )4 context.eval compiled_coffeescript5 end
![Page 20: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/20.jpg)
Pause
We have a JavaScript context (V8) at our finger tips
Have some basic CoffeeScript loading abilities
And some additional plumbing
Far from a DOM
![Page 21: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/21.jpg)
Server-side wrapper 1 class WaccLayout 2 3 def initialize( view, context = Javascript.new ) 4 @context = context 5 6 load_dependencies 7 8 # Pass our Ruby view into the context 9 @context["view"] = view10 11 # Setup12 @context.eval <<-EOJS13 var layout = new Demo.WaccLayout({14 view: view, data: data15 });16 EOJS17 end18 19 def render20 context['layout']['render'].methodcall( context['layout'] )21 end22 23 def load_dependencies24 @context.load_coffee Rails.root.join("app/assets/javascripts/wacc.js.coffee")25 @context.load_coffee Rails.root.join("app/assets/javascripts/wacc_layout.js.coffee")26 end27 end
![Page 22: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/22.jpg)
Server-side view & usage 1 class WaccPdf 2 3 def initialize 4 @pdf = Prawn::Document.new 5 end 6 7 def render( options ) 8 wacc = options.wacc 9 10 @pdf.text "WACC: #{wacc}"11 end12 13 end14 15 16 # Setup a view17 view = WaccPdf.new18 19 # Setup a layout and render20 layout = WaccLayout.new( view )21 layout.render
![Page 23: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/23.jpg)
1,000 ft view
![Page 24: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/24.jpg)
Reminder why we did it?
![Page 25: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/25.jpg)
![Page 26: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/26.jpg)
Yes please!
https://github.com/kennethkalmer/rubyfuza-2013
https://rubyfuza-2013-wacc.herokuapp.com
Later this weekend, you’re all getting drunk tonight anyway!!
![Page 27: Reusing your frontend JS on the server with V8/Rhino](https://reader034.vdocument.in/reader034/viewer/2022042714/555823ded8b42a25588b4cc6/html5/thumbnails/27.jpg)
Thank you!It’s been wild!