Rails provides a number of extensions to core Ruby classes. One of these is the to_sentence method, added to the Array class, allowing for the following:
['a', 'b', 'c'].to_sentence # gives: "a, b, and c"
I would like to extend this method to allow it to take a block, so that you can do something like the following (where people is an array of Person objects, which have the name attribute):
people.to_sentence { |person| person.name } # give something like: "Bill, John, and Mark"
I don't have a problem with writing the extension method. But I can't work out where to put it.
The Rails core extensions get loaded somewhere down in the depths of ActiveSupport.
My need is for a place where user-defined code is always loaded, and is pre-loaded (before any application code).
-
Create
config/initializers/super_to_sentence.rb. All files in this directory are loaded after Rails has been loaded, so you'll have a chance to override Rails' definition ofArray#to_sentence.For code you want to load before Rails gets loaded, add it to
config/environment.rb.cpjolicoeur : like was mentioned, add all your custom extensions to a config/initializers/*.rb filedcw : Thanks. Will check it out. -
I like to do this:
# 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 enddcw : Thanks. btw, I think it's good practice to remember the previous defn, i.e. add an "alias old_to_sentence to_sentence" before the defn of the new method and its aliasing. -
I think this is an ugly idea. Why dont you just write
people.collect { |person| person.name }.to_sentenceThis looks almost the same and will not confuse other people reading your code (like yourself in 2 years)
-
just searching around the web, seems like good practice is to add it in lib/
so if you wanna extend some ruby class (in my case, DateTime), just put the code in .rb and then in config/environment.rb:
config.after_initialize do require "lib/super_datetime.rb" endmy super_datetime.rb looks like this (code from 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 endrestart your server and you'll have access to the new method for all DateTime objects.
0 comments:
Post a Comment