Rails单表继承:如何定义带特定属性的子类模型
实现Tiger子类自动带species查询条件的正确方式
嘿,你想要的其实是Rails里**单表继承(STI)**的典型用法,不过因为你用的是species字段而不是Rails默认的type字段,需要稍微配置一下,比你现在的尝试要简单得多!
方法一:利用Rails内置STI机制(推荐)
这种方式最符合Rails的约定,自动帮你处理查询条件:
- 先在父类
Animal里指定继承字段为species:
class Animal < ApplicationRecord # 告诉Rails用species字段来区分不同子类 self.inheritance_column = :species end
- 然后定义
Tiger子类,只需要继承Animal,并指定它对应的species值(其实类名小写默认就是tiger,不过明确写出来更清晰):
class Tiger < Animal # 指定这个子类对应的species值 self.sti_name = "tiger" end
这样一来,Tiger.where(age: 12)就会自动转换成Animal.where(species: 'tiger').where(age: 12),完全符合你的需求!而且Rails还会自动处理实例的类型转换——比如从数据库查出来的species为tiger的记录,会自动实例化为Tiger对象。
方法二:用default_scope手动添加条件
如果你不想用STI的完整机制,也可以通过默认作用域来实现:
class Tiger < Animal default_scope { where(species: "tiger") } end
这种方式也能让Tiger.where(age:12)自动带上species='tiger'的条件,但相比STI,它不会自动处理实例类型转换,查询出来的对象还是Animal类型,除非你手动处理。
说说你之前尝试的问题
你用self.inherited来定义type方法的思路偏了,这个方法是用来处理子类继承时的回调,但并没有把species='tiger'的条件自动绑定到查询上,所以没法达到简化查询的效果。用上面两种方法中的任意一种,都能更优雅地实现需求~
内容的提问来源于stack exchange,提问作者Lee Chun Hoe
相关产品推荐
相关产品推荐

