Usually, your client side will be a web browser that can execute JS code without any third-party library, so ExecJS is not needed in this case (and wouldn't work, since ExecJS needs a Ruby interpreter, that is not available in any standard web browser).
In this case, I think Ryan just suggested you would use a Prawn::Document object inside your OrderPdf class, instead of inheriting from it. So for example, you would change:
ruby
classOrderPdf < Prawn::Documentdefinitializesuper
text "Order goes here"endend
(or use the delegate method mentionned by syath instead of writing your own render method)
In general, prefer composition to inheritance is considered good engineering practice because you control more tightly what your class exposes when you "use" an object rather than inheriting from it, so you have less surprises in the future.
For example, if a new version of Prawn renames the render function to render_document, you can just modify your own render method to use the new render_document one, instead of having to track every usage of render in your application. Or if you want to scrap Prawn and use another library, you can probably just modify your OrderPdf without rewriting a single line outside of it.
That's what we mean when we say that composition offer better encapsulation than inheritance.
Also means you could re-use the same JS file with another project. For example if you build a merchant hosting site where each of your users can create their own merchant site hosted by you, you could change easily who the payment is going to while using the same JS file for everyone.
Some peculiarities of Ruby's parser (nothing to do with Rails). Without self, it would think you are trying to assign a local stripe_customer_token variable instead of using the implicitly defined self.stripe_customer_token= attribute writer.
That would likely trigger a Stripe::InvalidRequestError when trying to Stripe::Customer.create( card: stripe_card_token) with your faked stripe_card_token, and thus prevent saving the subscription record.
Usually, your client side will be a web browser that can execute JS code without any third-party library, so ExecJS is not needed in this case (and wouldn't work, since ExecJS needs a Ruby interpreter, that is not available in any standard web browser).
In this case, I think Ryan just suggested you would use a
Prawn::Document
object inside yourOrderPdf
class, instead of inheriting from it. So for example, you would change:into:
(or use the
delegate
method mentionned by syath instead of writing your ownrender
method)In general, prefer composition to inheritance is considered good engineering practice because you control more tightly what your class exposes when you "use" an object rather than inheriting from it, so you have less surprises in the future.
For example, if a new version of Prawn renames the
render
function torender_document
, you can just modify your ownrender
method to use the newrender_document
one, instead of having to track every usage ofrender
in your application. Or if you want to scrap Prawn and use another library, you can probably just modify yourOrderPdf
without rewriting a single line outside of it.That's what we mean when we say that composition offer better encapsulation than inheritance.
Also means you could re-use the same JS file with another project. For example if you build a merchant hosting site where each of your users can create their own merchant site hosted by you, you could change easily who the payment is going to while using the same JS file for everyone.
Some peculiarities of Ruby's parser (nothing to do with Rails). Without
self
, it would think you are trying to assign a localstripe_customer_token
variable instead of using the implicitly definedself.stripe_customer_token=
attribute writer.That would likely trigger a
Stripe::InvalidRequestError
when trying toStripe::Customer.create( card: stripe_card_token)
with your fakedstripe_card_token
, and thus prevent saving the subscription record.