0

I'm sorry if this looks like a very easy (too easy) question but I'm struggling to find a way into working this out.

I need to calculate the Basal Metabolic Rate according to the data enter into a Body model and render it in my show view. The problem is that I can run the calculation in the view but, of course, this is not a proper way.

<%= ((13.397*@user.bodies.last.weight)+(479.9 * @user.bodies.last.height)-(5.677 * @user.bodies.last.age)+(88.362)) * (1 - (@user.bodies.last.fat / 100.00)) %>

this code snippet is in a partial that feeds Body#show view. Of course, I want to have this done at the controller level.

So I wrote a method in my bodies_controller that looks like this:

# Calculate Basal Metabolic Rate for Males
 def bmr
  @user = User.find(params[:user_id])
  @bmr = ((13.397 * @user.bodies.last.weight) + (479.9 * 
         @user.bodies.last.height) - (5.677 * @user.bodies.last.age) + 
         88.362) * (1 - (@user.bodies.last.fat / 100.00))
 end

When trying to pull the result of this simple calculation into my Body#show view like this: <%= @bmr %> nothing shows. Furthermore typing @bmr into the console returns NIL. How do I feed the Body attributes (Weight, age, height....) into the method?

Sorry if this question sounds stupid but I'm still learning.

Thanks a million in advance!

Shubham Jain
  • 16,610
  • 15
  • 78
  • 125

2 Answers2

0

you can move bmr method to body model as follow

body.rb

class Body < ApplicationRecord
 # your other codes 
 def bmr
  ((13.397 * self.weight) + 
    (479.9 * self.height) - 
    (5.677 * self.age) + 88.362) * 
    (1 - (self.fat / 100.00))
 end
end

for your note: self is equal to last bodies object

and from your view you can call the result as follow

show.html.erb

<%= @user.bodies.last.bmr %>
widjajayd
  • 6,090
  • 4
  • 30
  • 41
0

There are a few pointers I'd give you in solving this more elegantly. Breakdown the problem into more manageable parts, and try to stay away from magic numbers.

class Body
  def bmr
    @bmr ||= Bmr.calculate(self)
  end
end

(below) obviously, replace num1 etc. with descriptive names for those numbers so we have an idea of what they mean in this calculation. Also, consider using constants NUM1 defined at top of class instead of methods.

class Bmr
  attr_reader :body
  private :body

  def initialize(body)
    @body = body
  end

  def self.calculate(body)
    new(body).calculate
  end

  def calculate
    ((num1 * body.weight) +
     (num2 * body.height) - 
     (num3 * body.age) +
     (num4) *
     (num5 - (body.fat / 100.00)) 
  end

  def num1
    13.397
  end

  def num2
    479.9
  end

  def num3
    5.677
  end

  def num4
    88.362
  end

  def num5
    1
  end
end

On top of that, you could further break the inner calculations down..

def calculated_weight
  num1 * body.weight
end

# then

def calculate
  calculated_weight + calculated_height - calculated_age
  # etc
end

This gives you a great opportunity to describe the overall calculation and makes it much easier to grasp at a glance, and dig into if necessary.

Damien Roche
  • 13,189
  • 18
  • 68
  • 96