Ruby on Rails中模型之间的交互逻辑?

时间:2013-03-25 02:35:33

标签: ruby-on-rails ruby design-patterns refactoring models

我正在研究Rails,现在正试图组织模型之间的互动。我写的东西有效,但我认为代码闻起来很糟糕。

例如,我有两个包含数据库表ParcelWarehouse的模型。当我创建一个新的包时,我想增加与这个新包相关的Warehouse实例的:current_weight

同样,一切都有效,但是这种类型的代码,两个不同对象之间的交互,将经常被使用,而我脑海中的一些内容则说:“老兄,这段代码很糟糕,将来会引发问题!”。

也许有一些好的做法可以组织或重构它?也许是的 更好地为这种交互创建通用模块,甚至创建 使用通用method_missingput_方法的remove_逻辑, check_,例如warehouse.put_parcelwarehouse.remove_parcel

在ruby控制台中:

parcel = Parcel.new
parcel.weight = 10
parcel.warehouse_id = 1
parcel.save

# Create parcel and increase :current_weight of related warehouse by 10 after save

warehouse.rb:

class Warehouse < ActiveRecord::Base
    has_many :parcels
  attr_accessible :name, :current_weight
end

parcel.rb:

class Parcel < ActiveRecord::Base
    belongs_to :warehouse
    belongs_to :vehicle
  attr_accessible :name, :weight, :warehouse_id, :vehicle_id

  after_save :set_current_weight

  #Bad code:
  def set_current_weight
    @wh = self.warehouse
    @wh.current_weight = @wh.current_weight + self.weight
    @wh.save
  end
end

2 个答案:

答案 0 :(得分:1)

怎么样

warehouse.parcels.sum(:weight)

这样您就可以根据当前数据运行“实时”查询,而不是递增。

您当前型号稍微简洁一点:

  def set_current_weight
    @wh = self.warehouse
    @wh.current_weight += self.weight
    @wh.save
  end

答案 1 :(得分:0)

仓库的current_weight实际上不属于Parcel对象任务的一部分。你也给了它不止一个改变的理由。因此,这打破了single responsibility principle

我建议完全删除:current_weightset_current_weight。像这样得到仓库内的总重量:

def Warehouse < ActiveRecord::Base
  has_many :parcels
  # ...

  def current_weight
    parcels.sum(:weight)
  end
end

正如@muttonlamb在他的帖子中所建议的那样。