Использование as_json и динамического метода - PullRequest
0 голосов
/ 29 декабря 2018

У меня есть простой класс (без Rails)

class Tax

  attr_reader :guest_age

  def initialize(guest_age)
    @guest_age = guest_age
  end

  def amount
    0
  end

end

У этого объекта есть пользовательский метод "amount", и я хочу включить результат суммы в json, когда я делаю это: tax.as_json(methods: :amount)

Но это не работает, это возвращает только объект с переменными.

Что я получаю сейчас:

{"guest_age": 18}

Я ожидаю:

{"guest_age": 18, "amount": 0}

См. https://apidock.com/rails/ActiveModel/Serializers/JSON/as_json

Примечание:

Я хочу сохранить этот объект без зависимости от активной библиотеки записей.

Ответы [ 3 ]

0 голосов
/ 29 декабря 2018

Протестировано с 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.

0 голосов
/ 29 декабря 2018

опция метода работает для активного объекта модели.

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

0 голосов
/ 29 декабря 2018

Можете ли вы определить пользовательский метод в вашем классе?

  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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...