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

如何处置增强ActiveRecord::Base的rb文件

浏览 2184 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-11-06  
现在做一个全文检索的功能,需要在model加上这么一段代码:
def self.full_text_search(q, options = {})  
    return nil if q.nil? or q==""  
    default_options = {:limit => 10, :page => 1}  
    options = default_options.merge options  
    
    # get the offset based on what page we're on  
    options[:offset] = options[:limit] * (options.delete(:page).to_i-1)  
    results = this.find_by_contents(q, options)
  end


我有多个model需要加上全文检索的功能,现在的做法是在每个model都cp这段代码过去,cp的坏处也就不多说了。

因为每个model都是自ActiveRecord::Base继承而来,而且ruby有强大的open class功能,应该是可以这样的:
新建一个open_ar.rb文件
module ActiveRecord 
  class Base
    def self.full_text_search(q, options = {})  
      return nil if q.nil? or q==""  
      default_options = {:limit => 10, :page => 1}  
      options = default_options.merge options  
    
      # get the offset based on what page we're on  
      options[:offset] = options[:limit] * (options.delete(:page).to_i-1)  
      results = this.find_by_contents(q, options)
    end
  end
end

这样当可以一劳永逸。
那么在rails的目录结构中,我新建的这个open_ar.rb文件,应该放在那个目录下呢?
我是想遵循rails默认的目录结构来放置这个文件。
我想应该有不少DX会hack一下rails代码的吧,不过没找到过相关的资料。那位兄弟知道的话,请留言告之,感激不尽...

我觉得可行的做法是放到lib下:
RAILS_ROOT/lib/open_ar.rb
然后在 RAILS_ROOT/config/initializers/new_rails_defaults.rb中
require "lib/open_ar"

这样配置rails启动即加载此文件,达到增强AR,减少重复代码的效果。

此法纯粹是YY,未经实践,切忽模仿。
明晚实践一下这个做法。
   发表时间:2008-11-07  
今晚实践了一把,证实此法可行!
代码有些地方要修正,把要hack的代码放在lib/open_active_record_base.rb中:
module ActiveRecord
  class Base
    class << self
      #全文检索方法
      def full_text_search(q, options = {})  
        return nil if q.nil? or q==""  
        default_options = {:limit => 10, :page => 1}  
        options = default_options.merge options  
    
        # get the offset based on what page we're on  
        options[:offset] = options[:limit] * (options.delete(:page).to_i-1)  
        results = self.find_by_contents(q, options)
      end
    end
  end
end

使用单例类来定义全文检索的方法full_text_search,并要注意
results = self.find_by_contents(q, options)

中的 self ,由于这个方法在单例类中定义的,所以在子类中调用这个方法的时候 self 就表示子类。
因而可以在子类中这样使用:
Page.find_by_contents(q, options)


在rails中这样使用:
在environment.rb中加上一句:
require File.join(File.dirname(__FILE__),'..', 'lib','open_active_record_base') 

这样的意思是在rails启动的时候加载这个文件,从而达到增强ActiveRecord的效果。
0 请登录后投票
   发表时间:2008-11-07  
如有更cool的方法,请不吝指教。
0 请登录后投票
   发表时间:2008-11-07  
直接放到application.rb中就行了。
0 请登录后投票
   发表时间:2008-11-07  
jack 写道
直接放到application.rb中就行了。


此法虽然可行,但个人一直不认同把这种东西都放到application.rb中.如果以后还做这种事,也继续放在application.rb中吗?我觉得application.rb中的代码将会变得凌乱.
一直比较欣赏ruby中小方法的简洁风格(就是一个方法里就一两行代码),所以我觉得不同用途的代码还是分开比较好,在application.rb中来个大杂烩,不是明智之举.
0 请登录后投票
   发表时间:2008-11-07  
要简单就丢application.rb中,不需要require,如果要独立,那就放一个rb文件中,然后在application.rb中require,就可以了。

大杂烩吗,看情况咯,如果是application.rb中就加这么点代码,怎么都不会杂的,除非你已经放了很多内容进去了。
0 请登录后投票
   发表时间:2008-11-07  
哦耶,莫非是我把简单的问题想复杂,罪过,罪过...
0 请登录后投票
论坛首页 编程语言技术版

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