Как изменить атрибуты экземпляра ActiveRecord перед его отображением - PullRequest
0 голосов
/ 02 ноября 2018

В моем проекте Rails у меня есть модель class Employee < ActiveRecord::Base, у класса есть атрибут с именем компенсация , это тип данных : jsonb в Postgresql.

  create_table "employee" do |t|                       
    ...
    t.jsonb    "compensation"
    ...
  end

Компенсация содержит заработную плату, working_hours, start_from и т. Д.

compensation : {
  salary: 50000,
  working_hours: 230,
  start_from: 2018-12-21,
  ...
}

То, что я хочу сделать, это то, что перед тем, как экземпляр Employee будет отображен как JSON и ответ на внешний интерфейс, мне нужно удалить атрибут зарплаты в компенсации . В employee_controller я пытался использовать

def get_without_salary
  employee = Employee.find 2
  employee.compensation.delete :salary
  jsonapi_render json: employee
end

но результат JSON по-прежнему содержит данные о зарплате. Я могу заставить его работать только:

  temp_compensation = employee.compensation.dup
  temp_compensation.delete :salary
  employee.compensation = temp_compensation

но это слишком уродливо и смущает меня, почему первый путь не удался.

Может кто-нибудь объяснить мне, почему? Спасибо

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Подумав несколько дней, я нашел решение, которое сначала преобразует экземпляр active_record в хеш, затем удаляет зарплату из хеша, а затем преобразует хэш в экземпляр active_record. Это лучшее решение по сравнению с мутацией объекта на лету.

def get_without_salary
  employee = Employee.find 2
  filtered_employee = filter_salary employee
  jsonapi_render json: filtered_employee
end

def filter_salary(employee)
  record_hash = employee.as_json.deep_symbolize_keys!
  record_hash[:compensation]&.delete :salary
  Employee.new(record_hash)
end
0 голосов
/ 02 ноября 2018

Это кажется довольно сложным вопросом. Опции для as_json следующие:

  1. includes: => используется для включения has_many и belongs_to ассоциаций
  2. methods: => включить результат метода класса модели
  3. except: => запретить показ столбцов
  4. only: => показывать только указанные столбцы

Я пытался некоторые из них указать только некоторые атрибуты столбца jsonb, но они либо не работают, либо выдают NoMethodError: undefined method 'serializable_hash' for #<Hash:0x00000005082eb0>, показывая, что он пытается сериализовать ваш jsonb, но не удается.

Я думаю, что чистый способ сделать это может состоять в том, чтобы в вашей модели был метод filtered_compensation, в котором вы определяете json, который вы хотите отправить, и предотвращаете показ compensation.

def get_without_salary
  employee = Employee.find 2
  jsonapi_render json: employee.as_json(methods: [:filtered_compensation], except: [:compensation])
end

Где filtered_compensation заявлено в вашей модели

def filtered_compensation
  compensation.except 'salary'
end

Я думаю, что это соответствует чистоте, разделяет проблемы и делает ваш метод filtered_compensation для использования в других местах.

Обратите внимание, что вместо того, чтобы иметь в своем ответе атрибут compensation, вы найдете filtered_compensation, так как это имя метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...