I'm studying Rails and am now trying to organize interaction among models. What I've written works, but I think that the code smells bad.
For example, I have two models with database tables Parcel
and Warehouse
. When I create a new Parcel, I want to increase the :current_weight
of the Warehouse instance which is related to this new Parcel.
Again, everything works, but this type of code, interaction between two different objects, will be used frequently and something deep in my mind says: "Dude, this code sucks and will cause problems in the future!".
Maybe there are some good practices to organize or refactor it? Maybe it's
better to create a universal module for such interactions, or even create
method_missing
logic to use methods with universal put_
, remove_
,
check_
, like warehouse.put_parcel
and warehouse.remove_parcel
.
In ruby console:
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
How about
warehouse.parcels.sum(:weight)
That way you are running a 'live' query based on the current data, rather the incrementing.
Slightly more terse version of your current model too:
def set_current_weight
@wh = self.warehouse
@wh.current_weight += self.weight
@wh.save
end