2009-07-22 26 views
14

Giả sử tôi muốn lưu một số biến trong bộ điều khiển của mình. Tôi muốn khởi tạo nó trong một hành động, tăng nó trong một hành động khác, và đọc nó trong một hành động khác. Chỉ cần khai báo biến này với @foo không hoạt động vì @foo chết sau khi hành động tạo ra nó được hiển thị.
Tôi không muốn biến này được lưu trữ trong một mô hình.Làm thế nào để lưu trữ một biến mẫu trên nhiều hành động trong một bộ điều khiển?

Có cách nào để bảo toàn biến này ngoài việc lưu trữ biến đó trong phiên không?
Có vẻ như tôi đã gặp phải vấn đề đơn giản này một vài lần, và tôi muốn biết cách tốt nhất để giải quyết nó.

Trả lời

22

Không thực sự. Mỗi cuộc gọi đến một hành động điều khiển là không trạng thái. Không có gì khả dụng sau khi thao tác bộ điều khiển kết thúc. Một cá thể bộ điều khiển mới được tạo ra cho mỗi yêu cầu, và sau đó bị loại bỏ ở cuối yêu cầu.

Nếu bạn không muốn lưu trữ trong phiên hoặc mô hình cơ sở dữ liệu, bạn không có nhiều tùy chọn nếu bạn muốn biến đó cụ thể cho một phiên cụ thể.

Nếu nó là toàn cầu trên tất cả các phiên, bạn có thể đặt nó trong một @@class_variable thay vì @instance_variable, nhưng điều đó có thể lộn xộn một khi bạn bắt đầu có nhiều quy trình Rails (mỗi quy trình sẽ có bản sao của riêng nó) hoặc bạn đang chạy trong chế độ threadsafe, bạn có thể kết thúc với các lỗi đồng thời khó chịu.

Tôi đoán bạn có thể nhìn vào một cái gì đó giống như memcached, nhưng bạn vẫn sẽ cần phải quan trọng mà một số user_id hoặc đánh dấu phiên khác (trừ khi đó là toàn cầu)

7

Bạn có thể tận dụng được xây dựng trong Rails.cache cơ chế để lưu trữ giá trị nhưng như đã đề cập trong câu trả lời đầu tiên, bạn phải khóa nó ra một cái gì đó giống như user_id. Đây là một cách hay để đi vì bạn có thể quay lại với các cơ chế lưu trữ khác nhau.

Rails.cache.write(:foo) 
# in later action 
Rails.cache.read(:foo) 

Một điều khác bạn có thể xem là băm flash, cung cấp phương pháp giữ giá trị flash kéo dài hơn một yêu cầu tiếp theo.

Vì vậy, trong hành động 1 bạn có thể tạo ra giá trị:

flash[:foo] = some_value 
flash.keep(:foo) 

Trong hành động 2 bạn có thể truy cập vào nó, và gọi giữ lại nếu bạn muốn nó để sống cho những hành động tiếp theo nữa.

flash[:foo] #use it for something 
flash.keep(:foo) # keep it for another request 

Đó là một điều phức tạp để làm sạch trong bối cảnh yêu cầu http.

+0

Cache là một ý tưởng hay, nhưng tôi không nghĩ rằng phương thức flash sẽ hoạt động nếu bạn có nhiều máy chủ web. – Scott

+0

Tùy thuộc vào dung lượng lưu trữ phiên của bạn vì băm flash thực sự được lưu trữ trong phiên - ví dụ: nếu phiên bị tắt chỉ flash.now sẽ hoạt động – paulthenerd

+0

Bộ nhớ cache là một ý tưởng không sao. Nhưng nếu nó đang sử dụng MemoryStore, nó cho mỗi bộ nhớ quá trình, do đó, trừ khi bạn có một quá trình xử lý tất cả các yêu cầu, bạn yêu cầu tiếp theo có thể không nhấn quá trình có nó trong bộ nhớ. Nếu lưu trữ bộ nhớ được hỗ trợ bởi memcached, nó sẽ tốt hơn nhiều. –

1

Nếu đó là một số hoặc chuỗi đơn giản, tôi nghĩ giải pháp tốt nhất là lưu trữ nó trong phiên. Bằng cách đó, nó sẽ ở đó nếu bạn đang sử dụng nhiều máy chủ web.

Tại sao bạn không sử dụng phiên làm việc này?

+0

Tôi khá mới với Rails, và tôi chỉ giả định rằng phiên là dành cho * Những điều quan trọng * như một ID người dùng, không phải thứ gì đó tầm thường như một bộ đếm. Cảm ơn. –

11

Tôi cũng tự hỏi tại sao bạn không dùng phiên? Nếu bạn không thích làm việc trực tiếp với phiên trong hành động của mình, bạn có thể mô phỏng biến thể cá thể @foo còn tồn tại với các bộ lọc. Một cái gì đó như thế này có thể?

class FooController < ApplicationController 
    before_filter :load_foo 
    after_filter :save_foo 

    private 
    def load_foo 
     @foo = session[:foo] || 0 
    end 

    def save_foo 
     session[:foo] = @foo 
    end 

end 

Hành động của bạn sẽ có thể thao tác giá trị thông qua biến thể hiện @count và điều này sẽ tự động được duy trì cho phiên.

1

Đừng lo, các phiên sẽ không bị ảnh hưởng.

Ngoài ra, phiên có lẽ là cách tốt nhất để thực hiện việc này.

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