You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails中如何将select_tag的order_source参数传入模型验证器?

如何将order_source参数传入CashInOrder模型的验证器?

问题背景

你遇到的NoMethodError核心原因很明确:你的CashInOrder模型没有定义order_source属性,虽然表单提交时参数传过来了,控制器也允许了该参数,但因为模型没有对应的属性(不管是数据库字段还是虚拟属性),实例自然访问不到这个值。

解决办法

这里有两种可行的方案,你可以根据需求选择:

方案1:给模型添加数据库字段(推荐,适合需要持久化支付来源的场景)

如果你需要记录用户选择的支付卡ID,后续可能需要查询或关联,直接给cash_in_orders表加字段是最稳妥的:

  1. 生成迁移文件:
    rails generate migration AddOrderSourceToCashInOrders order_source:string
    
  2. 运行迁移:
    rails db:migrate
    

这样处理后,cash_in_order_params里的order_source会被自动赋值给模型实例的属性,验证器里self.order_source就能正常调用了。

方案2:使用虚拟属性(适合不需要持久化该字段的场景)

如果不需要把order_source存到数据库,只需要在验证时临时使用,可以给模型添加虚拟属性:
在CashInOrder模型顶部添加:

class CashInOrder < ApplicationRecord
  attr_accessor :order_source # 添加这行
  validate :is_cashed_in
  # ... 其他代码
end

attr_accessor会给模型实例创建对应的getter和setter方法,控制器的参数会自动赋值给这个虚拟属性,验证器里就能正常访问self.order_source了。

额外需要修正的小问题

除了上面的核心问题,你的验证器里还有个小bug:

Stripe::Charge.create(:amount => (amount.to_f*100).to_i, ...)

这里的amount变量没有定义,应该改成self.order_sum,也就是:

Stripe::Charge.create(:amount => (self.order_sum.to_f*100).to_i, :currency => 'usd', :source => card.id, :customer => self.deposit.user.stripe_customer_id)

另外,你的控制器create方法里调用了两次@cash_in_order.save,第一次在if current_user...判断里,第二次在respond_to块里,这会导致重复执行保存逻辑,建议去掉第一次的@cash_in_order.save,只保留respond_to里的判断。

内容的提问来源于stack exchange,提问作者anndrew78

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 09:42:37