【问题标题】:Trying to return a virtual attribute through User serializer in Rails尝试通过 Rails 中的用户序列化程序返回虚拟属性
【发布时间】:2016-06-15 19:18:14
【问题描述】:

我的模型中定义了一个虚拟属性:

class User < ActiveRecord::Base
  attr_writer :tdee
  attr_reader :tdee
  include Authentication
  has_many :examples
  has_many :meals, inverse_of: :user

  def tdee
    if gender == 'f'
      bmr = 655 + (9.6 * (weight * 0.453592)) + (1.8 * (height * 2.54)) - (4.7 * age)
    elsif gender == 'm'
      bmr = 66 + (13.7 * (weight * 0.453592)) + (5 * (height * 2.54)) - (6.8 * age)
    end
    tdee = bmr * activity_level
  end
end

我可以在我的 rails 控制台和控制器中访问它。当我索引/显示用户时,我希望它包含在 json 中,所以我假设我必须编辑我的用户序列化程序。目前我的序列化程序看起来像我的迁移生成的默认值:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :email, :height, :weight, :age, :activity_level, :gender

end

我尝试过类似的方法:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :email, :height, :weight, :age, :activity_level, :gender, :tdee

  def tdee
    tdee = @user.tdee
  end

end

我一直得到

NoMethodError (undefined method `tdee' for nil:NilClass):
  app/serializers/user_serializer.rb:6:in `tdee'
  app/controllers/users_controller.rb:48:in `index'

this 等其他一些问题谈到了使用 to_json,但我不确定如何在我的上下文中实现这一点,因为我没有使用该方法构建用户信息。

编辑:

如下所示,我需要使用 object.tdee。更新后,我仍然收到无方法错误,因为计算虚拟所需的属性值为零。更新这些解决了这个问题。

【问题讨论】:

    标签: ruby-on-rails serialization


    【解决方案1】:

    您需要在序列化程序中使用对象,而不是使用 @user。请注意,序列化程序看不到控制器设置的实例变量

    def tdee
      object.tdee
    end
    

    你不需要 tdee =。查看这篇博文http://eewang.github.io/blog/2013/07/23/using-activemodel-serializers-to-build-great-json-interfaces/

    【讨论】:

    • 返回NoMethodError (undefined method '*' for nil:NilClass): app/models/user.rb:15:in 'tdee' app/serializers/user_serializer.rb:6:in 'tdee' app/controllers/users_controller.rb:48:in 'index'
    • 我可以在我的序列化程序中定义我的虚拟属性吗?这样我就可以避免在我的模型中看不到我的定义。
    • 运行rails控制台时可以返回tdee的值吗?尝试使用 user = User.last 和 user.tdee 获取记录。它有效吗?序列化程序可以使用 object.method_name 返回自定义方法,但从错误看来,您正在尝试将 * 与 nill 值相乘,这是您无法做到的。我想说检查您的 User 模型类中的方法,并确保您的公式中没有 nil 值。
    • 所以它通过 Rails 控制台工作。但是只有一个用户拥有计算 TDEE 所需的数据集。所以你的意思是我的其他两个用户没有这个数据集,当我使用显示操作(访问所有用户)时,丢失的数据会引发错误?
    • 是的,如果您将它们全部序列化,例如索引操作。因此,您将需要在模型中添加例如不会生成异常的逻辑。为了在您的序列化程序中进行快速测试,请将 object.tdee 包裹在 begin rescue 块中,但只是看看它是否正常工作。然后你可以做的是在你的用户模型中重构 def tdee 并实现安全验证,比如 if self.width && self.height....等
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    • 2013-08-20
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    相关资源
    最近更新 更多