as_json和动态方法的用法

时间:2018-12-28 22:54:58

标签: ruby-on-rails ruby

我有一个简单的课程(没有Rails)

class Tax

  attr_reader :guest_age

  def initialize(guest_age)
    @guest_age = guest_age
  end

  def amount
    0
  end

end

此对象具有“金额”自定义方法 并且我想在执行此操作时将金额结果包括在json中:tax.as_json(methods: :amount)

但这不起作用,它只返回带有变量的对象。

我现在得到的是:

  

{“来宾年龄”:18}

我期望的是:

  

{“来宾年龄”:18,“数量”:0}

请参见https://apidock.com/rails/ActiveModel/Serializers/JSON/as_json

注意:

我要保留此对象而不具有活动记录库依赖性。

3 个答案:

答案 0 :(得分:3)

经过Rails 5.2.2的测试,这是as_json的来源:

def as_json(options = nil) #:nodoc:
  if respond_to?(:to_hash)
    to_hash.as_json(options)
  else
    instance_values.as_json(options)
  end
end

这意味着,如果您在类中实现to_hash方法,则as_json调用将按照您希望的方式工作:

class Tax

  attr_reader :guest_age

  def initialize(guest_age)
    @guest_age = guest_age
  end

  def amount
    0
  end

  def to_hash
    instance_values.merge(amount: amount)
  end
end

然后...

Tax.new(1).as_json
# => {"guest_age"=>1, "amount"=>0}

尽管这总是包括amount,但似乎没有一个简单的方法可以解决。

它的工作方式可能有所不同,您需要明确丢弃amount

Tax.new(1).as_json(except: :amount)
# => {"guest_age"=>1}

或明确指定要序列化的属性:

Tax.new(1).as_json(only: "guest_age")
# => {"guest_age"=>1}

您要使用的methods选项似乎严格地与ActiveRecord关联。

答案 1 :(得分:2)

您可以在类中定义自定义方法吗?

  def to_h
    {guest_age: @guest_age, amount: amount}
  end

因此您可以致电:

tax = Tax.new(18)
p tax.to_h
#=> {:guest_age=>18, :amount=>0}

require 'json'
puts tax.to_h.to_json
#=> {"guest_age":18,"amount":0}

答案 2 :(得分:1)

方法选项适用于活动模型对象。

class Tax

  include ActiveModel::Serialization
  include ActiveModel::Serializers::JSON

  attr_accessor :guest_age

  def initialize(guest_age)
    @guest_age = guest_age
  end

  def attributes
    {'guest_age' => nil}
  end

  def amount
    0
  end

end

这样的代码应该可以工作,有关更多信息,请参见源代码。

https://github.com/rails/rails/blob/master/activemodel/lib/active_model/serialization.rb

https://github.com/rails/rails/blob/master/activemodel/lib/active_model/serializers/json.rb