2009-04-14 24 views
5

Ai đó hiểu cách hoạt động của bộ nhớ đệm đường ray có thể thực sự giúp tôi ở đây. Dưới đây là đoạn code, lồng vào bên trong của khối Rails :: Initializer.run:Hằng số được đặt trong môi trường.rb biến mất trong chế độ phát triển

config.after_initialize do 
    SomeClass.const_set 'SOME_CONST', 'SOME_VAL' 
end 

Bây giờ nếu tôi chạy script/server và thực hiện một yêu cầu, tất cả mọi thứ là dandy. Tuy nhiên, trên yêu cầu thứ hai cho ứng dụng Rails của tôi, tất cả đi vào địa ngục với một lỗi liên tục đơn vị. Trong chế độ sản xuất, tôi có thể thực hiện yêu cầu thứ hai thành công, có nghĩa là hằng số vẫn còn đó.

Tôi đã khắc phục vấn đề bằng cách thay đổi trên để:

config.after_initialize do 
    require 'some_class' # in RAILS_ROOT/lib/some_class.rb 
    SomeClass.const_set 'SOME_CONST', 'SOME_VAL' 
end 

Nhưng bây giờ có nghĩa là bất cứ khi nào tôi thực hiện một sự thay đổi để some_class.rb, tôi phải khởi động lại máy chủ. Có cách nào để thiết lập hằng số trong một tập tin môi trường và có họ làm việc một cách chính xác trong chế độ phát triển? Tại sao hằng số tồn tại trên yêu cầu đầu tiên, nhưng không tồn tại yêu cầu sau?

UPDATE: Kể từ environment.rb chỉ đọc khi ứng dụng Rails được khởi động và tôi muốn cả hai tập tin và các mô hình lib của tôi để được nạp lại vào từng yêu cầu, tôi đã buộc phải di chuyển hằng vào file some_class.rb như sau:

if Rails.env.development? 
    const_set 'SOME_CONST', 'SOME_DEVELOPMENT_VAL' 
end 

Và trong môi trường/production.rb, tôi có mã const_set cũ.

CẬP NHẬT: Phương pháp tốt hơn bằng cách sử dụng config.to_prepare được nêu chi tiết bên dưới.

Trả lời

9

Nó chỉ hoạt động theo yêu cầu đầu tiên trong chế độ phát triển vì các lớp được tải lại theo từng yêu cầu. Vì vậy, trên yêu cầu đầu tiên hằng số được thiết lập trong initializer, và tất cả là tốt. Sau đó, trên yêu cầu tiếp theo, nó tải lại lớp WITHOUT rerunning bit từ initializer của bạn, do đó, hằng số không được thiết lập từ đó trên ra ngoài.

Nó hoạt động trong chế độ sản xuất vì các lớp không được tải lại cho mỗi yêu cầu, do đó bạn không bị mất trạng thái lớp đó mỗi lần.

Vì vậy, bạn có thể muốn đặt hằng số trong mô hình hoặc trong một số config.to_prepare thay vì config.after_initialize. to_prepare được gọi trước mỗi yêu cầu.

Trong mô hình:

class SomeClass < ActiveRecord::Base 
    MY_CONST = "whatever" 

    # You can access MY_CONST directly, but I tend to wrap them in a class 
    # method because literal constants often get refactored into the database. 
    def self.my_const 
    MY_CONST 
    end 
end 

Trong cấu hình:

# This will run before every single request. You probably only want this in 
# the development config. 
config.to_prepare do 
    SomeClass.const_set 'SOME_CONST', 'SOME_VAL' 
end 
+0

Cảm ơn bạn, đó chính là câu trả lời tôi đang tìm kiếm. – joshuaxls

+0

Những cái ôm và những nụ hôn với @joshuaxls và @Sarah Mei, trời ơi, điều này thực sự đã giúp tôi rất nhiều! – clacke

+0

Tải lại các lớp học mà không cần chạy bộ khởi tạo là một điều thực sự ... có thể thông minh, nhưng rất khó hiểu. – clacke

1

Chế độ sản xuất tải trước tất cả các lớp, trong khi các lớp chế độ phát triển được tải khi cần, sau các tệp cấu hình được đọc. Yêu cầu thủ công chúng trong các cấu hình của bạn buộc các lớp được đọc trước/trong giai đoạn cấu hình.

+0

tôi vẫn tự hỏi tại sao mặc dù nó hoạt động trên yêu cầu đầu tiên và không phải là yêu cầu sau đây. Và bạn có biết bất kỳ cách nào để thiết lập các hằng số trong một tệp môi trường sao cho chúng tồn tại trong chế độ phát triển không? Tôi đang thực hiện rất nhiều thay đổi đối với some_class.rb và không muốn tiếp tục khởi động lại máy chủ. – joshuaxls

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