手动定义getter / setter时如何使用read_attribute(attr_accessor或attr_writers)

我设置了一个search模型,并且要求至少填写一个字段。 我发现了一个有助于validation的问题, Rails:如何要求至少一个字段不为空 。 (我尝试了所有答案,但Voyta似乎是最好的。)

validation工作正常,除非我想通过attr_accessorattr_writer重新定义getter / setter。 (我在表单上有虚拟属性,需要分开validation。)为了弄清问题是什么,我测试了一个常规属性item_length属性。 如果我添加attr_accessor :item_length ,validation将停止工作。 所以,我想问题是如何在不使用点表示法的情况下读取属性的值。 由于validation使用字符串,我无法使用正常的阅读方式。

这是一个片段:

 if %w(keywords item_length item_length_feet item_length_inches).all?{|attr| read_attribute(attr).blank?} errors.add(:base, "Please fill out at least one field") end 

就像我说的那样,虚拟的attrbutes(length_inches和length_feet)完全不起作用,普通的属性(length)也可以工作,除非我重新定义了getter / setter。

如评论中所述,请使用send

 array.all? {|attr| send(attr).blank?} 

对于那些想知道在这种情况下send是否正常的人,是的是:对象调用自己的实例方法。

但是send是一个很好的工具,所以无论何时使用其他对象, public_send确保将public api与public_send

您应该将read_attribute视为读取Active Record列的私有方法。 否则你应该总是直接使用读者。

 self.read_attribute(:item_length) # does not work self.item_length # ok 

由于您尝试动态调用它,因此可以使用genericsruby方法public_send来调用指定的方法

 self.public_send(:item_length) # the same as self.item_length