Rails 5 + Mongoid 项目中模型Concerns通用函数抽象实现问题
在Rails 5 + Mongoid中使用Model Concern抽象通用函数
嘿,我来帮你搞定在Mongoid里用Concern抽象通用函数的事儿!其实和你之前用ActiveRecord的思路基本一致,但有几个Mongoid特有的细节要留意,咱们一步步来:
1. 创建通用Concern文件
首先在app/models/concerns目录下创建你的通用Concern文件,比如genericable.rb,用ActiveSupport::Concern来包装通用逻辑,示例如下:
# app/models/concerns/genericable.rb module Genericable extend ActiveSupport::Concern # 通用类方法示例:获取最近N条创建的记录 module ClassMethods def recent(limit = 10) order(created_at: :desc).limit(limit) end # 通用类方法:筛选包含非空数组字段的记录 def with_non_empty_array(field) where(field.ne => []).where(field.exists => true) end end # 通用实例方法示例:格式化年份为字符串 def formatted_year year.strftime("%Y") if year.present? end end
2. 在Mongoid模型中引入Concern
回到你的Movie模型,这里要提醒你一个容易踩的坑:你同时定义了field :writers, type: Array和has_many :writers,这会导致命名冲突!Mongoid无法区分你指的是数组字段还是关联模型,得把其中一个改名。下面是修正后的完整模型代码:
# app/models/movie.rb class Movie include Mongoid::Document include Genericable # 引入通用Concern field :name, type: String field :year, type: Date field :length, type: Integer field :writer_names, type: Array # 改名避免和关联冲突 validates_presence_of :name, :year, :length validates_uniqueness_of :name index({name: 1}, {unique: true}) # 假设你有Writer模型,关联名修改为避免冲突 has_many :movie_writers, class_name: "Writer", dependent: :destroy end
3. 验证通用方法是否生效
现在你就能在代码里直接复用Concern里的通用方法了:
- 类方法调用:
Movie.recent(5)会返回最近创建的5部电影;Movie.with_non_empty_array(:writer_names)会返回有编剧名字的电影 - 实例方法调用:
Movie.first.formatted_year会返回电影年份的字符串格式(比如"2023")
这样就把通用逻辑成功抽象到Concern里了,后续其他Mongoid模型也可以直接include Genericable来复用这些方法~
内容的提问来源于stack exchange,提问作者Marc Pursals
相关产品推荐
相关产品推荐

