#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