API Rails: как отобразить пользовательский атрибут модели в контроллере?

#ruby-on-rails

#ruby-on-rails

Вопрос:

В действии #index в моем контроллере я отображаю модель, как показано ниже. Хотя я хотел бы включить пользовательский атрибут, но он никогда не отображается, как я могу это сделать?

 class MyModel < ApplicationRecord
  def custom_attr
    attr1   attr2
  end
end
  
 class MyModelsController < ApplicationController
  def index
    # 'custom-attr' is not rendered.
    render json: MyModel.all, status: :ok, only: %i[attr1, attr2, custom_attr]
  end
end
  

Комментарии:

1. Посмотрите на драгоценные камни, например blueprinter , добавленный уровень сериализации значительно упрощает выполнение подобных действий.

Ответ №1:

Это не атрибут. Это просто метод экземпляра. attributes действительно ли это специфичная для Rails особенность моделей, которая на самом деле является установщиком / получателем в сочетании с метаданными.

 class Person
  include ActiveModel::Model
  include ActiveModel::Attributes
  attribute :name
  attribute :age
end

irb(main):009:0> Person.new.attributes
=> {"name"=>nil, "age"=>nil, "birthplace"=>nil}
  

Когда вы отображаете модель как JSON, rails использует #as_json вызовы which #serializeable_hash для модели. Это сериализует атрибуты на основе метода attributes . Именно здесь фактически передаются параметры.

Поскольку #custom_attr на самом деле это не атрибут, он, конечно, не включен в сериализацию.

Вы можете решить это с помощью:

  • Переопределите #as_json модель, чтобы настроить ее сериализацию.
  • Используйте уровень сериализатора, такой как ActiveModel::Serializers или JBuilder, чтобы настроить представление модели в формате JSON. (рекомендуется)

Комментарии:

1. Я вижу, не могу ли я иметь вычисляемый атрибут в моей модели, который не хранится в БД?

2. Я понял, спасибо. 🙂 хотя, в моем примере, как бы вы сделали его доступным только для чтения и вычисляли?

3. Самый простой способ сделать это — просто использовать MyModel.select("*", "CONCAT('attr', ' ', 'attr2') AS custom_attr") . Rails автоматически преобразует любые столбцы в результирующем наборе в атрибуты. Правильный способ — использовать вместо этого уровень сериализации.

4. Я просто хочу иметь атрибут, доступный только для чтения, который вычисляется, как в примере, который я привел. Я не понимаю, почему я изо всех сил пытаюсь найти то, что, на мой взгляд, является основным. ^^ Я не хочу писать пользовательский SQL, мне нужно вычислить их в Ruby;

5. ActiveModel::Serializers больше не поддерживается, они сами перечисляют некоторые альтернативы здесь github.com/rails-api/active_model_serializers#status-of-ams