0

I'm trying to keep my code DRY.

I have two virtually identical methods for calculating the cost of certain products. The formula is $35 for the first item and $15 for every subsequent item, unless a customer has credits, then the first x items are free where x = customer.credits

I keep the prices in a Setting model like so:

Setting.first_item_cost # Set to 35
Setting.item_cost       # Set to 15

The method in ruby looks like this:

def calc_subtotal
  output = 0.0
  primary = Setting.first_item_cost # 35 - Cost of first item
  secondary = Setting.item_cost # 15 - Cost of subsequent items
  items.each_with_index do |item, i|
    unless i < customer.credits
      output += i == 0 ? primary : secondary
    end
  end
  return output
end

Meanwhile on my page I update the subtotals live with JavaScript

let price_prime = parseFloat("#{Setting.first_item_cost}");
let price_other = parseFloat("#{Setting.item_cost}");
let credit = parseInt("#{current_customer.credits}");

function calculatePrice( count ){
  var output = 0.0;
  if( count < 0 ) count = 0;
  for (i = 1; i <= count; i++ ){
    var price = ( i == 1 ) ? price_prime : price_other;
    output += ( i > credit ) ? price : 0.0;
  }
  return output;
}

So the formulas are close to identical in the different programing languages. Obviously for security reasons I can't just let the client side JavaScript dictate the price, and I'd rather not have to do an AJAX call every time somebody updates the quantity of their order (though that may be the only solution)

What I want to know is if there's a way to DRY this; perhaps by passing the formula from Ruby to JavaScript?

Okomikeruko
  • 1,123
  • 10
  • 22
  • 2
    If you want to rephrase the question, *is there a way to run Ruby code in the browser?* Then the answer is **yes** - through [Native Client Language](https://developer.chrome.com/native-client/overview). But before you get to excited its not a widely supported feature and some duplication between backend and frontend code is always unavoidable. https://dev.to/wuz/stop-trying-to-be-so-dry-instead-write-everything-twice-wet-5g33 – max Jul 24 '20 at 16:38
  • Maybe an easier answer would be to go the other direction and evaluate the JavaScript code on the back end (see https://github.com/rubyjs/therubyracer). Alternatively, if your functions could be written as pure mathematical expressions, you could write them in something like MathML or LaTeX and try to find libraries for both Ruby and Javascript that can evaluate that. – Stephen Crosby Jul 25 '20 at 20:20

0 Answers0