Как показать расчет в контроллере для представления (Rails) - PullRequest
0 голосов
/ 25 апреля 2018

Я создаю веб-сайт, который может хранить данные измерений тела и рассчитывать жировые отложения по формуле Джексона / Поллока 7.Я довольно новичок в рельсах и не уверен, как я могу вывести вычисления из контроллера измерений в show.html.

Measurements_controller.rb метод вычисления:

def calculate

  bodyDensityMale = 1.112 - (0.00043499 * (@measurement.chest + @measurement.Midaxillary + @measurement.Tricep+@measurement.Subscapular+@measurement.Abdominal
+@measurement.Suprailiac+@measurement.Thigh)) + (0.00000055 * (@measurement.chest+@measurement.Midaxillary+@measurement.Tricep+@measurement.Subscapular+@measurement.Abdominal
+@measurement.Suprailiac+@measurement.Thigh)^2) - (0.00028826 * @measurement.age)

  bodyDensityFemale = 1.097 - (0.00046971 * (@measurement.chest + @measurement.Midaxillary+@measurement.Tricep+@measurement.Subscapular+@measurement.Abdominal
+@measurement.Suprailiac+@measurement.Thigh)) + (0.00000056 * (@measurement.chest+@measurement.Midaxillary+@measurement.Tricep+@measurement.Subscapular+@measurement.Abdominal
+@measurement.Suprailiac+@measurement.Thigh)^2) - (0.00012828 * @measurement.age)

  bodyFatMale = (495 / bodyDensityMale) - 450
  bodyFatFemale = (495 / bodyDensityFemale) - 450

  if (@measurement.gender_type = 'Male')
    puts bodyFatMale
  else
    puts bodyFatFemale
  end
end

show.html.erb

<p>
    <strong>Body Fat (%): </strong>
    <%= @measurement.calculate %>
</p>

Когда я создаю запись, ошибок нет, но поле% содержания жира отображается пустым.Я ценю любую помощь!

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Несколько замечаний:

1) Обязательно соблюдайте Соглашения о присвоении имен Ruby : используйте символ змеи для символов, методов и переменных (например, bodyDensityMale должно быть body_density_male иMidaxillary, Tricep и т. Д. Должны быть midaxillary, tricep)

2) ^ - двоичный XOR-оператор Ruby .** для показателей.

3) В состоянии вашего контроллера имеется ошибка из-за = против ==.

if (@measurement.gender_type = 'Male')

должно быть

if (@measurement.gender_type == 'Male')

Первым присваивается значение, поэтому оно всегда будет истинным.== для сравнения на равенство.

Логика вычислений лучше всего перемещать из контроллера в модель или класс обслуживания.Вот два решения для помещения его в модель Measurement:

################################################################################
# Solution #1
################################################################################
class Measurement
  MALE = 'Male'

  def body_fat
    (495 / body_density) - 450
  end

  def body_density
    gender_type == MALE ? body_density_male : body_density_female
  end

  def body_density_male
    1.112 -
    (0.00043499 * body_density_sum) +
    (0.00000055 * body_density_sum ** 2) -
    (0.00028826 * age)
  end

  def body_density_female
    1.097 -
    (0.00046971 * body_density_sum) +
    (0.00000056 * body_density_sum ** 2) -
    (0.00012828 * age)
  end

  def body_density_sum
    [chest, midaxillary, tricep, subscapular, abdominal, suprailiac, thigh].sum
  end
end

################################################################################
# Solution #2 using subclasses
################################################################################
class Measurement
  def body_fat
    (495 / body_density) - 450
  end

  def body_density_sum
    [chest, midaxillary, tricep, subscapular, abdominal, suprailiac, thigh].sum
  end
end

class MaleMeasurement < Measurement
  def body_density
    1.112 -
    (0.00043499 * body_density_sum) +
    (0.00000055 * body_density_sum ** 2) -
    (0.00028826 * age)
  end
end

class FemaleMeasurement < Measurement
  def body_density
    1.097 -
    (0.00046971 * body_density_sum) +
    (0.00000056 * body_density_sum ** 2) -
    (0.00012828 * age)
  end
end

Чтобы использовать Solution # 2 с подклассами, вы должны были бы настроить модель Measurement и таблицу базы данных, используя singleнаследование таблиц .Решение № 1 не потребует никаких изменений в базе данных и, вероятно, будет самым быстрым / простым (вы могли бы провести рефакторинг в будущем).

С любым из этих решений, на ваш взгляд:

<p>
  <strong>Body Fat (%): </strong>
  <%= @measurement.body_fat %>
</p>
0 голосов
/ 25 апреля 2018

Похоже, ваша основная проблема в том, что вы звоните calculate на @measurement здесь:

<p>
  <strong>Body Fat (%): </strong>
  <%= @measurement.calculate %>
</p>

Но, похоже, логика calculate в контроллере.Я не знаю, как выглядит метод calculate на @measurement, но, очевидно, он возвращает nil или что-то подобное.

На вашем месте я бы перенес всю эту логику в класс BodyFatCalculator, что-то вроде:

class BodyFatCalculator

  # using a constant makes it a *little* easier to make sure you don't have
  # a typo in your constant values
  CONST_VALUES = {
    male: {
      one:    1.112,
      two:    0.00043499,
      three:  0.00000055,
      four:   0.00028826
    },
    female: {
      one:    1.097,
      two:    0.00046971,
      three:  0.00000056,
      four:   0.00012828
    }
  }

  # this just defines the methods 'const_one', 'const_two', etc. that
  # return the appropriate constant from above. The const_val
  # method is defined below.
  [:one, :two, :three, :four].each do |const_ref|
    define_method("const_#{const_ref}") do 
      const_val const_ref
    end
  end

  # provides a getter/setter for @measurement
  attr_accessor :measurement

  class << self

    # class-level method that lets you do BodyFatCalculator.calculate.
    # Requires that a 'measurement' is passed in as an argument.
    def calculate(measurement)
      new(measurement).calculate
    end

  end

  # sets the @measurement instance variable.
  def initialize(measurement)
    @measurement = measurement
  end

  # does the calculation
  def calculate
    (495 / body_density) - 450
  end

  # calculates body density. I think this is a *little* more readable
  # so that it's easier to see if you have the formula right. The 'const_one',
  # 'const_two', etc. methods were defined at the top. 
  # The `sum_two` method is defined below.
  def body_density
    const_one - ( const_two * sum_two ) + ( const_three * sum_two^2 ) + ( const_four * measurement.age )
  end

  # given a type (like ':one', ':two', etc.), uses 'measurement.gender_type'
  # to return the correct constant.
  def const_value(type)
    CONST_VALUES[measurement.gender_type.underscore.to_sym][type]
  end

  # given an array of names, will sum the values from '@measurement'
  # that correspond to the name.
  def sum_of *names
    names.each_with_object(0) do |name, sum|
      sum += measurement.send(name)
    end
  end

  # sum of a specific set of values from '@measurement'.
  def sum_two
    @sum_two ||= sum_of(*w(chest Midaxillary Tricep Subscapular Abdominal Suprailiac Thigh))
  end

end

(ВНИМАНИЕ: не проверялось.)

Затем в вашем контроллере сделайте что-то вроде:

def show
  @body_fat = BodyFatCalculator.calculate(@measurement)
end

И на ваш взгляд:

<p>
  <strong>Body Fat (%): </strong>
  <%= @body_fat %>
</p>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...