重新定义Rails的方法

Rails方法Array#to_sentence允许以下内容:

 ['a', 'b', 'c'].to_sentence # gives: "a, b, and c" 

我想扩展这个方法以允许它占用一个块,这样你就可以执行以下操作(其中people是Person对象的数组,具有name属性):

 people.to_sentence { |person| person.name } # => "Bill, John, and Mark" 

编写扩展方法时没有问题。 但我无法弄清楚在哪里放。 Rails核心扩展在ActiveSupport的深处被加载到某处。 我需要一个总是加载用户定义代码的地方,并预先加载(在任何应用程序代码之前)。

创建config/initializers/super_to_sentence.rb 。 加载Rails后,将加载此目录中的所有文件,因此您将有机会覆盖Rails对Array#to_sentence的定义。

对于要在加载Rails之前加载的代码,将其添加到config/environment.rb

我喜欢这样做:

 # config/initializers/app.rb Dir[File.join(Rails.root, "lib", "core_ext", "*.rb")].each {|l| require l } # lib/core_ext/array.rb class Array def to_sentence_with_block(*args, &block) if block_given? # do something... # to_sentence_without_block(*args) perhaps? else to_sentence_without_block(*args) end end alias_method_chain :to_sentence, :block end 

我认为这是一个丑陋的想法。 你为什么不写

 people.collect { |person| person.name }.to_sentence 

这看起来几乎相同,不会混淆其他阅读代码的人(比如2年内你自己)

只是在网上搜索,似乎很好的做法是在lib /中添加它

所以,如果你想扩展一些ruby类(在我的例子中,DateTime),只需将代码放在.rb中,然后放在config / environment.rb中:

  config.after_initialize do require "lib/super_datetime.rb" end 

我的super_datetime.rb看起来像这样(代码来自http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/140184 ):

 class DateTime def days_in_month self::class.civil(year, month, -1).day end alias dim days_in_month def weekdays (1..dim).to_a end end 

重新启动服务器,您将可以访问所有DateTime对象的新方法。