codeinspired codeinspired - 1 year ago 88
Ruby Question

How to create a method to calculate minutes per mile in Ruby on Rails

In my Rails 4.2.6 / Ruby 2.2.4 project, I have a cardio exercise model with duration, distance and average pace fields. "Duration" and "average pace" are time datatypes; "distance" is a decimal datatype. I need help writing a method to calculate a user's average pace (minutes per mile) based on a user's inputs in the duration and distance fields.

* EDIT *

The duration and distance fields in my cardio exercises form (_form.html.erb):

<div class="cardio_duration">
<%= f.input :duration do %> <br>
<%= f.time_select :duration, :include_blank => true, include_seconds: true %>
<% end %>

<div class="cardio-time">
<%= f.input :distance, :include_blank => true %>
<% end %>

Here's what I have coded so far in my cardio exercise model:

before_save { self.average_pace = self.calculate_average_pace } # calls calculate average pace method

I understand that when calculating minutes per mile, the time factor is on top in the equation. Here's the method I've written:

def calculate_average_pace
duration = self.duration
distance = self.distance
average_pace = duration / distance

When I execute this method, it generates the following error:

undefined method `/' for 2000-01-01 16:50:00 UTC:Time

I'm trying to do something like this: 26 minutes / 1.17 miles, which equals 22.29 minutes per mile. How should I change my code to fix the problem? Thanks for the help & explanation.

**EDIT **

This is the relevant DB schema:

create_table "cardio_exercises", force: :cascade do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.time "duration"
t.decimal "distance"
t.time "average_pace"

Answer Source

You're getting undefined_method error because you're trying to divide Time by Decimal. Only Numeric values can be divided.

I tried to achive that functionality like this.

# _form.html
# ...
  <div class="field">
    <%= f.label :duration %><br>
    <%= f.time_select :duration, include_blank: false, include_seconds: true %>
# ...

# Cardio model
class Cardio < ActiveRecord::Base
  before_save :set_mpm

  def set_mpm
    # find minutes from time entered by user
    mins = duration.hour * 60 + duration.min + duration.sec / 60
    self.mpm = mins / distance

# controller
  def create
    @cardio =

    respond_to do |format|
        format.html { redirect_to @cardio, notice: 'Cardio was successfully created.' }
        format.json { render action: 'show', status: :created, location: @cardio }
        format.html { render action: 'new' }
        format.json { render json: @cardio.errors, status: :unprocessable_entity }

Here is the result


Is that works for you?


1 hour for 10 miles works for me.


Here is my DB schema.

  create_table "cardios", force: :cascade do |t|
    t.time     "duration"
    t.decimal  "distance"
    t.decimal  "mpm"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download