【问题标题】:Calculation in model or controller在模型或控制器中计算
【发布时间】:2016-06-01 19:58:58
【问题描述】:

我正在构建一个减肥应用程序。为此,在我的应用程序中,每个用户 has_one :profilehas_many :weights。每个配置文件belongs_to :pal。为了让我的应用程序正常工作,我需要一个名为 SMR 的值,它基本上是一个公式,它将用户的大小、年龄和性别(全部来自配置文件表)、用户当前的体重(来自权重表)以及来自的浮点数作为变量朋友表。

我能够在profiles_controller.rb show action 中计算 SMR 并将其显示在配置文件 show.html.erb 中。

我现在有两个问题:

  1. profiles_controller.rb 显示操作中进行此计算是否正确,还是应该在profile.rb 模型中进行?如果我应该在模型中做:我该怎么做(代码应该是什么样子)?
  2. 稍后我将在我的应用程序中需要 SMR 值作为其他计算的变量。我怎样才能做到这一点(如果它是在配置文件控制器/模型中计算但稍后需要在其他地方)?

我对 Rails 世界还很陌生,所以也许我的问题真的是菜鸟问题。

profile.rb

class Profile < ActiveRecord::Base
  belongs_to :user
  belongs_to :pal
  belongs_to :goal


  def age
    if birthdate != nil
      now = Time.now.utc.to_date
      now.year - birthdate.year - (birthdate.to_date.change(:year => now.year) > now ? 1 : 0)
    else
      nil
    end
  end
end 

weight.rb

class Weight < ActiveRecord::Base
  belongs_to :user
end

pal.rb

class Pal < ActiveRecord::Base
  has_many :profiles
end

profiles_controller.rb(仅显示操作)

  def show
    @pal = @profile.pal
    @goal = @profile.goal
    @current_weight = Weight.where(:user_id => current_user.id).order(:day).last

    if @profile.gender == 0
      @smr = (10*@current_weight.kilograms+6.25*@profile.size-5*@profile.age+5)*@pal.value
    elsif @profile.gender == 1
      @smr = (10*@current_weight.kilograms+6.25*@profile.size-5*@profile.age-161)*@pal.value
    else
      nil
    end
  end

【问题讨论】:

  • 你的直觉是正确的!模型中没有计算,您可以在更有意义的模型中进行,或者创建一个接收profilecurrent_weigh 的Calculator 类并进行计算。关于“我以后可能需要它”,我看到你每天有一个体重。您可以将针对该重量和当天计算的 SMR 存储在表格本身中,然后在其他任何地方进行查询。如果不存在 SMR,请计算并保存。
  • 在服务中进行计算

标签: ruby-on-rails


【解决方案1】:

我认为你应该创建一个单独的类,或者你也可以在配置文件模型上做

class SmrCalculator
  def initialize(profile, user)
     @profile = profile
     @user = user
  end

  def get_smr
    @pal = @profile.pal
    @goal = @profile.goal
    @current_weight = Weight.where(:user_id => @user.id).order(:day).last

    if @profile.gender == 0
      @smr = (10*@current_weight.kilograms+6.25*@profile.size-5*@profile.age+5)*@pal.value
    elsif @profile.gender == 1
      @smr = (10*@current_weight.kilograms+6.25*@profile.size-5*@profile.age-161)*@pal.value
    else
      nil
    end
  @smr
  end

end

然后像这样在你的控制器显示方法上调用这个类:

@smr_calculator = SmrCalculator.new(@profile, current_user)
@smr = @smr_calculator.get_smr

并将这个类添加为模型文件夹中的 smr_calculator.rb

所以在应用程序中您需要@smr 的任何地方,您都可以使用个人资料和当前用户调用此类

【讨论】:

  • 太棒了!正是我想要的!非常感谢。
【解决方案2】:

您可以在app 文件夹中创建一个services 目录。在其中您可以将您的类创建为CalculatorService

例子:

class CalculatorService
  def initialize(profile, user)
     @profile = profile
     @user = user
  end

  def smr_value
    @pal = @profile.pal
    @goal = @profile.goal
    @current_weight = Weight.users_weight(@user.id)

    @smr = if @profile.gender == 0
      (10*@current_weight.kilograms + 6.25*@profile.size-5*@profile.age+5)*@pal.value
    elsif @profile.gender == 1
      (10*@current_weight.kilograms + 6.25*@profile.size-5*@profile.age-161)*@pal.value
    else
      nil
    end
    @smr
  end
end

 class Weight < ActiveRecord::Base
   scope :users_weight, ->(user_id) { where(:user_id => user_id).order(:day).last}
end

并像这样在您的控制器中调用此服务:

@smr_calculator = CalculatorService.new(@profile, current_user)
@smr = @smr_calculator.smr_value 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多