众所周知,thinking-sphinx 提供了 Real-Time 和 Delta 两种索引,而我在项目中经常使用后者。 使用这种方式,通常你会遇到这样一个问题:
If you are using associations for field or attribute data, delta indexing will not automatically happen when you make changes to those association models. You will need to add a manual delta hook to make it all update accordingly.
举个例子:
Article model 有这样索引:
indexes comments.content, :as => :comments
当 comments 有变化(更新或删除), article.comments 是不会自动重新索引的; 为使其重新索引, 我们不得不 Do a hack:
# comment.rb
after_save :set_article_delta_flag
after_destroy :set_article_delta_flag
# ...
private
def set_article_delta_flag
article.delta = true
article.save
end
代码很简单,满足需求,是否意味这个 fearch 就可以结束? 当深入一想,这样的代码并不通用,因为一个项目会有很多类似模型,我们总不能将这样的代码到处 copy 吧。
我们的解决方案:
1.新建一个共用模块:
# app/models/concerns/auto_touch_delta_flag.rb
module AutoTouchDeltaFlag
def auto_touch_associations(*associations)
set_delta_flag = proc do
associations.each do |association|
association_model = self.send(association)
association_model.delta = true
association_model.save
end
end
after_save set_delta_flag
after_destroy set_delta_flag
end
end
2.在 ActiveRecord::Base 注入此模块
# config/initializers/active_record_concerns.rb
ActiveRecord::Base.extend SphinxAssociationDeltaCallback
3.在需要的模型里通过 auto_touch_associations 方法,注入需要观察的关联对象:
# comment.rb
auto_touch_associations :article
总结:完成代码功能并非难事,但我们需要多一些思考,消除可见重复,让代码变的更好。