Rails:在对另一个模型进行更改时更新多个模型的最佳方法

时间:2015-05-21 01:40:06

标签: ruby-on-rails ruby

我正在构建一个包含模型AutomaticMatch的Rails 4.2应用程序,用于存储Account(用户个人资料)和Assignment之间的匹配分数。 AccountAutomaticMatch之间存在很多关系,Assignments也是如此。我有一些存储在帮助器中的方法来计算得分:

#Calculates the total compatibility score between an account and an assignment
#Returns a decimal which is the percent of compatibility

def total_score_assign(account,assign)
  score_categories = score_categories_assign(account,assign)
  sum = 0
  categories = (assign.skills.map{|h| h.category}).uniq

  score_categories.each do |k,v|
   sum += v
  end

  total = sum / categories.size
end

所以,我想在保存AutomaticMatch之前触发分数的计算并创建相应的Assignment db记录,并在AutomaticMatch时重新计算+更新Assignment记录}或Account已更新。 我的问题是,实现这个的最佳方法是什么,因为我应该在另一个模型中发生变化时在不同模型上执行CRUD操作?  经过一些研究,我发现了以下方法:

  • 应用策略模式并在我执行这些操作时创建服务类
  • 使用ActiveRecord回调并在AutomaticMatch模型中执行这些操作
  • 使用观察员

现在我很困惑,因为我不知道是否有Rails方法可以做到这一点以及上面哪一个是,如果有的话。这是我在Rails中的第一个大项目,我还不太了解大型应用程序特有的问题和实践,所以我非常感谢您的见解。

1 个答案:

答案 0 :(得分:1)

一个非常酷的项目,提供pub / sub并允许服务类响应来自各种应用程序事件的消息:https://github.com/krisleech/wisper - 您可以注册侦听器并使用服务对象响应通知。我发现它是一种非常有用的方法来避免依赖并保持代码更有条理。将作业推送到后台进程以避免阻塞等也非常容易。以下是可以在此处找到的文章的修改摘录:http://www.toptal.com/ruby-on-rails/the-publish-subscribe-pattern-on-rails

# app/listener/feed_listener.rb
class FeedListener
  def post_create(post)
    Services::FeedService.create!(post)
  end
end

# app/controllers/api/v1/posts_controller.rb
# corresponds to the publisher in the previous figure
class Api::V1::PostsController < Api::V1::ApiController
  def create
    @post = current_user.posts.build(post_params)
    if @post.save
      # Publish event about post creation for any interested listeners
      publish(:post_create, @post)
      render_created(@post)
    end 
  end
end

# config/initializers/wisper.rb
Wisper.subscribe(FeedListener.new)

这是我发现保持关注点分离,划分服务代码并防止我的模型和控制器变得太胖的最好方法。