重新定义Rails的方法

时间:2009-05-09 00:17:21

标签: ruby-on-rails ruby

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的深处向下加载。 我需要一个总是加载用户定义代码的地方,并预先加载(在任何应用程序代码之前)。

4 个答案:

答案 0 :(得分:23)

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

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

答案 1 :(得分:14)

我喜欢这样做:

# 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

答案 2 :(得分:14)

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

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

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

答案 3 :(得分:1)

只是在网上搜索,似乎很好的做法是在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对象的新方法。