在我的Rails项目中,我有一个模型class Employee < ActiveRecord::Base
,该类具有名为 compensation 的属性,它是Postgresql中的:jsonb数据类型。
create_table "employee" do |t|
...
t.jsonb "compensation"
...
end
薪酬包含薪水,工作时间,起始时间等
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
但这太丑陋,使我困惑为什么第一种方法失败了。
有人可以向我解释为什么吗?谢谢
答案 0 :(得分:0)
这似乎是一个棘手的问题。 as_json
的选项如下:
includes:
=>过去包括has_many
和belongs_to
关联methods:
=>包含模型的类方法的结果except:
=>防止显示showig列only:
=>仅显示指定的列我尝试其中的一些方法仅指定jsonb
列的某些属性,但是它们不起作用或抛出NoMethodError: undefined method 'serializable_hash' for #<Hash:0x00000005082eb0>
,表明它试图序列化jsonb
但失败。 / p>
我认为一种干净的方法可能是在模型中有一个方法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
,因为它是方法的名称。
答案 1 :(得分:0)
经过几天的思考,我提出了一个解决方案,该解决方案首先将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