注意:本文小写的变量都为实例变量,如:employee
使用 polymorphic
场景: Employee 和 Product 都 has_many pictures, 但是又不希望创建两个类似的 pictures 表。也就是我们希望Employee 和 Product 可以同时关联上 Picture, 最后能从 pictures 表中各取所需,也可以在 Picture 的每个实例对象中获得所属对象。最终结果:
- rails 中
|
|
- 存在表里的是:
| id | name | imageable_id | imageable_type |
|---|---|---|---|
| 1 | sun | 1 | Product |
| 2 | moon | 1 | Employee |
- 示例代码
|
|
- 注意事项
model 中的 imageable 需要与表中的 imageable_id 和 imageable_type 对应,如果你的是 object_id 和 object_type,那么 model 中应该是 belongs_to :object, polymorphic: true
覆盖 Picture 中的 imageable
上述代码中,Product 有 scope,当你用 picture.imageable 的时候,会把 scope 也带上,有可能你需要的是所有的 imageable ,而不是 scope 下的,这个时候可以通过覆盖掉 imageable 这个方法来解决。
比如:
|
|
这里面通过 imageable_type 获取类名,constantize 把字符串的类名转化为对象,再调用 unscoped 方法,最后通过 imageable_id 找到具体的 imageable 对象。定义 @imageable 是为了一次请求中不多次查询imageable,因为 rails 会缓存。
根据 RubyChina 上的反馈做出调整
参考:https://ruby-china.org/topics/34429
- 一开始文中写的是 scope ,是写错了,现在改正过来了。
- 最好不使用 default_scope
如果非要使用 default_scope 可以用比文中更好一点的解决方法:(此方法发现 bug ,暂时还是不使用了,因为我们暂时不牵扯到)
1belongs_to :imageable, -> { unscope(:where) }, polymorphic: true文中的方法会导致 includes 无效等问题。