Sinatra+ActiveRecord下Recurrent类initialize方法参数不匹配问题
解决ActiveRecord子类重写initialize方法导致的参数错误问题
你遇到的这个参数矛盾问题,本质是因为ActiveRecord(AR)的模型子类不能直接重写initialize方法。
问题根源
在纯Ruby环境里,子类重写initialize完全没问题,但ActiveRecord的模型继承自ActiveRecord::Base,它自带的初始化逻辑是专门为处理属性哈希、关联加载等场景设计的——默认只接受0或1个参数(可选的属性哈希)。你自定义的带2个参数的initialize覆盖了AR的初始化方法,两边的参数规则冲突,就出现了"给2个参数但期望0..1"或者反过来的错误。
解决方案
推荐用工厂方法替代重写initialize,这样既能保留AR的原生功能,又能实现你的自定义初始化需求:
class Recurrent < Entry attr_accessor :date_1, :date_2, :monthly_entry # 定义工厂类方法,封装自定义初始化逻辑 def self.from_dates(date_1, date_2) recurrent = new # 调用AR原生的初始化方法 recurrent.date_1 = date_1 recurrent.date_2 = date_2 recurrent end # 其他方法 end
调用的时候就用这个工厂方法:
date_1 = DateTime.new(2020,12,5) date_2 = DateTime.new(2021,11,5) recurrent = Recurrent.from_dates(date_1, date_2)
如果你一定要重写initialize,必须先调用super来执行AR的初始化逻辑,同时兼容AR的参数规则:
class Recurrent < Entry attr_accessor :date_1, :date_2, :monthly_entry def initialize(date_1 = nil, date_2 = nil, attributes = {}) super(attributes) # 先执行AR的初始化逻辑 @date_1 = date_1 if date_1 @date_2 = date_2 if date_2 end # 其他方法 end
这种方式既支持你的参数调用,也兼容AR的属性赋值(比如Recurrent.new(date1, date2, {bankaccount_id: 1})),但要注意如果属性哈希里有和date_1/date_2同名的键,可能会出现覆盖问题,所以还是工厂方法更稳妥。
内容的提问来源于stack exchange,提问作者thiebo
相关产品推荐
相关产品推荐

