ruby-on-rails – 用于Rails的QueryObject – 如何在ActiveRecor
发布时间:2020-12-17 02:34:18 所属栏目:百科 来源:网络整理
导读:我如何封装一组操作(其中大部分基本上是.where(…))并将其应用于不同的模型,其方式是某些模型可能无法实现某些操作并应返回空集合. (跳过非必要代码) 我设计的(但不满意): class ActivityFinder def self.find(query,limit = nil) activities = get_activit
我如何封装一组操作(其中大部分基本上是.where(…))并将其应用于不同的模型,其方式是某些模型可能无法实现某些操作并应返回空集合. (跳过非必要代码)
我设计的(但不满意): class ActivityFinder def self.find(query,limit = nil) activities = get_activities(query) activities = activities.sort_by(&:created_at).reverse // some-kind of merge-sort activities = activities.slice(0,limit) if limit.present? activities end private def self.get_activities(query) activities = [] activities += query.apply(ModelA) activities += query.apply(ModelB) activities += query.apply(ModelC) activities end end class ActivityQuery def created_before(time) @created_before = time self end def created_after(time) @created_after = time self end def apply(activity) activity = activity.where("#{activity.table_name}.created_at < ?",@created_before) if @created_before.present? activity = activity.where("#{activity.table_name}.created_at >= ?",@created_after) if @created_after.present? // more operations,not all of them are suported by ModelC rescue NoMethodError return [] end end 用法 query = ActivityQuery.new.created_before(last_time).with_hash(...) activities = ActivityFinder.find(query) 我不喜欢的: >救援NoMethodError 所以我正在寻找更好实施的建议 UPDATE 问题是我想传递我从ActiveModel获得的任何对象,例如ActiveRecord :: Relation,所以我不能只用这些方法定义一个模块(并在需要时覆盖它)并将它包含在我正在使用的模型中.问题更多的是指向干净设计的正确方向,而不是实现细节,我会以某种方式弄清楚 解决方法
为避免紧耦合,请将特定于模型的代码放入模型中:
class ModelA < ActiveRecord::Base scope :created_before,->(timestamp) { where("created_at < ?",timestamp) } scope :created_after,->(timestamp) { where("created_at >= ?",timestamp) } scope :with_hash,->(hash) { ... } end class ModelB < ActiveRecord::Base scope :created_before,->(timestamp) { where("other_column < ?",->(timestamp) { where("other_column >= ?",where('false') # empty,chain-able collection end 现在您可以编写一个可编程的一致界面: class ActivityQuery def apply(activity) activity = activity.scoped activity = activity.created_before(@created_before) if @created_before.present? activity = activity.created_after(@created_after) if @created_after.present? activity = activity.with_hash(@hash) if @hash.present? activity end end 无需拯救NoMethodError,也无需更多地摆弄模型的实现细节. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |