Переопределение методов Rails
Метод Rails Array#to_sentence
допускает следующее:
['a', 'b', 'c'].to_sentence # gives: "a, b, and c"
Я хотел бы расширить этот метод, чтобы он мог взять блок, чтобы вы могли сделать что-то вроде следующего (где люди - это массив объектов Person, которые имеют атрибут name):
people.to_sentence { |person| person.name }
# => "Bill, John, and Mark"
У меня нет проблемы с написанием метода расширения. Но я не могу понять, где это сказать. Расширения ядра Rails загружаются где-то в глубину ActiveSupport
.
Моя потребность в месте, где пользовательский код всегда загружается и предварительно загружен (перед любым кодом приложения).
Ответы
Ответ 1
Создать config/initializers/super_to_sentence.rb
. Все файлы в этом каталоге загружаются после загрузки Rails, поэтому у вас будет возможность переопределить определение Rails Array#to_sentence
.
Для кода, который вы хотите загрузить до загрузки Rails, добавьте его в config/environment.rb
.
Ответ 2
Мне нравится делать это:
# 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
Ответ 3
Я думаю, что это уродливая идея. Почему вы просто не пишете
people.collect { |person| person.name }.to_sentence
Это выглядит почти так же и не путает других людей, читающих ваш код (например, себя через 2 года).
Ответ 4
просто поиск по сети, похоже, хорошая практика заключается в том, чтобы добавить его в lib/
поэтому, если вы хотите расширить класс ruby (в моем случае DateTime), просто поместите код в .rb, а затем в config/environment.rb:
config.after_initialize do
require "lib/super_datetime.rb"
end
my 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.