论坛首页 编程语言技术论坛

让rails中多态关联的方法名更加人性化

浏览 2792 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-12-02   最后修改:2008-12-02
rails中的多态关联功能,很好很强大。

但是多态关联的方法名却不够人性化,下面用代码来说话。

class Brand < ActiveRecord::Base
  has_many :evaluations,:as => :evaluation
end

class Page < ActiveRecord::Base
  has_many :evaluations,:as => :evaluation
end

class Evaluation < ActiveRecord::Base
  belongs_to :evaluation,:polymorphic => true
end


上面就是一个多态关联的经典代码,就不多说了。按代码的写法,当要在Evaluation中取Brand或者Page的值是,只能如此调用:
  evaluation.evaluation #Brand or Page

对于 evaluation.evaluation 这样的代码,你会不会感到有那么一点点的恶心呢?

假如可以这样:
  evaluation.brand # Brand 
  evaluation.page # Page

想必会更加的赏心悦目吧。

利用ruby的open class 和 method_missing 的特性,可以用下面的代码让代码更加美丽:
module ActiveRecord
  class Base
    def method_missing(name,*args)
      #      这个方法,可以自动对多态关联生成相关的名字(类名)
      resource = self.class.to_s.downcase
      if (self.respond_to? "#{resource}") && (self.send "#{resource}").class.to_s.downcase.eql?(name.to_s)
        self.send "#{resource}"
      elsif  (self.respond_to? "#{resource}=") && (self.send "#{resource}").class.to_s.downcase.eql?(name.to_s.sub('=',''))
        self.send "#{resource}",*args
      end
    end
end

你的 model 不用做任何的改动。

有时候美丽就是如此简单。

   发表时间:2008-12-03  
yy小说男又开始rb了
0 请登录后投票
   发表时间:2008-12-03  
上面的代码其实是有问题的,刚刚发现的。
正确代码如下:
   def method_missing(name,*args)
      puts "miss method :#{name}"
      #      这个方法,可以自动对多态关联生成相关的名字(类名)
      resource = self.class.to_s.downcase
      if (self.respond_to? "#{resource}") && (self.send "#{resource}").class.to_s.downcase.eql?(name.to_s)
        self.send "#{resource}"
      elsif  (self.respond_to? "#{resource}=") && (self.send "#{resource}").class.to_s.downcase.eql?(name.to_s.sub('=',''))
        self.send "#{resource}",*args
      else
        super
      end
    end

请注意最后:
     else
        super
      end

如果没有这个 super 的话,rails的魔术就不灵了,因为activerecord中自动为数据库字段增加访问方法也是用 method_missing的。
0 请登录后投票
   发表时间:2008-12-03   最后修改:2008-12-03
像这种多态一般写成

 class Evaluation < ActiveRecord::Base  
   belongs_to :evaluationable,:polymorphic => true  
 end  
0 请登录后投票
   发表时间:2008-12-03  
艾云 写道
yy小说男又开始rb了

放纵了几日,回归了。
0 请登录后投票
   发表时间:2008-12-03  
climber2002 写道
像这种多态一般写成

 class Evaluation < ActiveRecord::Base  
   belongs_to :evaluationable,:polymorphic => true  
 end  


你不觉得这样:
evaluation.brand # Brand   
evaluation.page # Page 

更加易读,更加容易理解吗?
0 请登录后投票
   发表时间:2008-12-30   最后修改:2008-12-30
不理解你想作什麼。

如果你要
evaluation.brand
evaluation.page

,根本不必搞什麼特別的東東。
class Brand < ActiveRecord::Base  
  has_many :evaluations
end  
   
class Page < ActiveRecord::Base  
  has_many :evaluations
end

class Evaluation < ActiveRecord::Base  
  belongs_to :brand
  belongs_to :page
end


命名係自行選擇。官方例體並無你的問題
class Asset < ActiveRecord::Base
  belongs_to :attachable, :polymorphic => true
end

class Post < ActiveRecord::Base
  has_many :assets, :as => :attachable
end

@asset.attachable = @post

不明白Brand與Page有何關係,我就亂作一個product。你可以改一個比較近人習用之名。
class Brand < ActiveRecord::Base  
  has_many :evaluations,:as => :product
end  
  
class Page < ActiveRecord::Base  
  has_many :evaluations,:as => :product
end  
   
class Evaluation < ActiveRecord::Base  
  belongs_to :product,:polymorphic => true  
end

@evalutation.product = Page.new
@page.evaluations << Evaluation.new

polymorphic relationship係為幫助性近之類,可以用統一method插口處理。不必各自分開。
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics