`
zizipo
  • 浏览: 22705 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

关于对象关联关系的一点感悟

阅读更多
这段时间一直在开发项目的后台部分。采用的方法是一个类一个类的设计,这样带来很大的一个问题,以后设计一定要分两步走,概要设计和细节设计,在概要设计里面,对核心流程设计的类都要先考虑。
我先设计Store类,每个用户在一个订单中会有一个快递速度的评分StoreOntimeScore.两者是一对多关系。但其实每次评分是关联到一个订单Order的。所以我的设计是Order has_one StoreOntimeScore.Store has_many Orders.Store has_many StoreOntimeScores through order.这个地方发现rails的一个bug.has_many不能through has_one,因为前几天也被这个家伙的一个bug搞死了,于是对他很是失望,之后就变成了对自己失望。
花了些时间来考虑怎么处理这个bug.
1.把has_one改为has_many,has_one也是一种特殊的has_many。代码改动很小,但逻辑上感觉总是那么不舒服。
2.不用through,在StoreOntimeScore直接加一个store_id,问题是冗余了,有可能不一致出错,并且也多了维护的代码。这个时候想到用元编程来解决这个问题。思路是在调用store_ontime_score.order=order,然程序自动设置store_ontime_score.store =store_ontime_score.order.store.于是有了下面需要extend进类的模块。
Module MyLib
def attr_related(origin,related)
    define_method :"#{origin}=_with_sophie_0923_related" do |param|
      self.send(:"#{origin}=_without_sophie_0923_related",param)
      self.send(:"#{related}=",self.send(origin).send(related))
    end
    alias_method_chain :"#{origin}=",:sophie_0923_related
  end
end

不得不说,这招虽然之后发现对我没有,但还是蛮强大的。不是到build方法是怎么实现的如果没有调用store=,build可能也要重写一些,不用build就不用。

因为这个是时候还没有考虑具体订单Order对象。当我开始设计具体的订单对象的时候发现,这个评分可以直接只是store的一个属性,于是开始疯狂删代码,删表ing...
这件事给我的教训:
1.慎用has_one,这个本来就是一一对应关系,数学上说,一一对应本来就可以看作是一个对象。如果真的要用has_one,我上面的代码和想法还是很不错的。这可能也是rails一直没有修复这个bug的原因
2.设计一定要分两部。
2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics