2009-05-09 25 views
16

Các Rails phương pháp Array#to_sentence phép sau:phương pháp Redefining Rails'

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

tôi muốn mở rộng phương pháp này để cho phép nó để có một khối, do đó bạn có thể làm một cái gì đó như sau (nơi mọi người là một mảng đối tượng Person có thuộc tính name):

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

Tôi không gặp vấn đề với việc viết phương thức mở rộng. Nhưng tôi không thể tìm ra nơi để đặt nó. Các phần mở rộng cốt lõi của Rails được tải ở một nơi nào đó ở độ sâu ActiveSupport. Nhu cầu của tôi là dành cho một nơi mà mã do người dùng định nghĩa luôn được tải và được tải trước (trước bất kỳ mã ứng dụng nào).

Trả lời

23

Tạo config/initializers/super_to_sentence.rb. Tất cả các tệp trong thư mục này được tải sau khi Rails đã được tải, vì vậy bạn sẽ có cơ hội ghi đè định nghĩa của Rails là Array#to_sentence.

Đối với mã bạn muốn tải trước khi Rails được tải, hãy thêm nó vào config/environment.rb.

+0

như đã được đề cập, thêm tất cả tiện ích mở rộng tùy chỉnh của bạn vào cấu hình/trình khởi tạo/* .bb file – cpjolicoeur

+0

Cảm ơn. Sẽ kiểm tra xem nó ra. – dcw

14

Tôi muốn làm điều này:

# 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 
+0

Cảm ơn. btw, tôi nghĩ rằng đó là thực hành tốt để nhớ defn trước đó, tức là thêm một "bí danh old_to_sentence to_sentence" trước khi defn của phương pháp mới và aliasing của nó. – dcw

14

Tôi nghĩ rằng đây là một ý tưởng xấu xí. Tại sao bạn không chỉ cần viết

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

này trông gần như giống nhau và sẽ không nhầm lẫn người khác đọc code của bạn (giống như bạn trong 2 năm)

+2

Và bây giờ, nó trở nên ngắn hơn: 'people.map (&: name) .to_sentence' – sawa

1

chỉ tìm kiếm khắp nơi trên web, có vẻ như thực hành tốt là thêm nó trong lib/

vì vậy nếu bạn muốn mở rộng một số lớp ruby ​​(trong trường hợp của tôi, DateTime), chỉ cần đặt mã trong rb và sau đó trong config/environment.rb:

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

super_datetime.rb của tôi trông như thế này (mã từ 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 

khởi động lại máy chủ của bạn và bạn sẽ có quyền truy cập vào các phương pháp mới cho tất cả các đối tượng DateTime.

Các vấn đề liên quan