Переопределение методов Rails - PullRequest
16 голосов
/ 09 мая 2009

Метод 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 ]

23 голосов
/ 09 мая 2009

Создать config/initializers/super_to_sentence.rb. Все файлы в этом каталоге загружаются после загрузки Rails, поэтому у вас будет возможность переопределить определение Rails для Array#to_sentence.

Если вы хотите загрузить код до загрузки Rails, добавьте его в config/environment.rb.

14 голосов
/ 12 мая 2009

Я думаю, что это ужасная идея. Почему ты просто не пишешь

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

Это выглядит почти так же и не смущает других людей, читающих ваш код (таких как вы через 2 года)

14 голосов
/ 09 мая 2009

Мне нравится это делать:

# 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
1 голос
/ 16 июля 2009

просто поиск по сети, похоже, хорошей практикой является добавление его в 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...