如何将Rails API接口的CalculationResolver计算结果传入Field类的result方法
实现方案
核心问题梳理
现有代码存在两处逻辑缺陷阻碍需求实现:
Field类的result方法为私有方法,且固定返回0,不支持接收外部传入的计算值- 控制器中
render方法放在计算逻辑之前,导致接口返回的是未计算的原始数据
具体改造步骤
- 第一步:调整
Field类的result方法,支持读写计算结果
class Field < ApplicationRecord belongs_to :calculator before_create :set_selector enum kind: { form: 0, parameter: 1, result: 2 } enum unit: { month: 0, date: 1, times: 2 } validates :type, :label, :kind, presence: true validates :unit, inclusion: { in: units.keys } # 改造为公共读写方法:不传参返回当前结果,传参则赋值 def result(value = nil) value.nil? ? (@result || 0) : @result = value end private def set_selector return if selector.present? selected_rows_count = Field.where(kind: kind).count if selected_rows_count.positive? previous_number = Field.where(kind: kind).last.selector[1] self.selector = kind[0].upcase + previous_number.next.to_s else self.selector = "#{kind[0].upcase}1" end end end
- 第二步:修正控制器执行顺序,实现计算结果赋值
module Api module V1 class CalculatorsController < ApplicationController def compute calculator = Calculator.find_by(slug: params['id']) # 兼容计算器不存在的异常场景 return render json: { error: '目标计算器不存在' }, status: :not_found unless calculator # 移除原代码错误的.result调用,直接取关联字段集合 @fields = calculator.fields @fields.each do |field| cal_res = CalculatorResolver.call(field.calculator) res = cal_res.each_with_object({}) do |(key, value), result| result[key[:value]] = value.each_with_object({}) do |v, sel| sel[v[:selector].downcase] = v[:value] end end res.each do |key, value| # 拿到计算结果后传入field的result方法赋值 calculation_result = CalculationResolver.result(value, key) field.result(calculation_result) end end # 全部计算完成后再执行渲染返回 render json: @fields, root: 'result', adapter: :json end end end end
- 第三步:序列化逻辑无需额外调整
原有FieldSerializer会自动调用field实例的result方法,返回我们已经赋值的计算结果。
内容的提问来源于stack exchange,提问作者Maksym
相关产品推荐
相关产品推荐

