2010-03-10 8 views
19

Tôi đang cố gắng truy cập một biến mẫu được đặt trong bộ điều khiển trong mô hình. Bộ điều khiển là bộ điều khiển sản phẩm và mô hình là mô hình sản phẩm. Biến cá thể là một cá thể của một mô hình khác được gọi là tài khoản.Ruby on Rails - Biến điều khiển truy cập từ mô hình

Biến dụ là @current_account

Khi tôi chạy mã có gì xảy ra, tôi không nhận được một lỗi. Có ai biết nơi tôi có thể tìm thấy một cái gì đó đọc về các biến thể truy cập thiết lập trong bộ điều khiển từ mô hình?

Cảm ơn

Eef

+0

Vì vậy, bạn đang cố truy cập biến @current_account trong mô hình? Biến @current_account đang được đặt trong bộ điều khiển? – Steve

Trả lời

46

Bạn thường không nên cố gắng truy cập bộ điều khiển từ mô hình cho các vấn đề có đầu óc cao mà tôi sẽ không tham gia.

tôi giải quyết một vấn đề tương tự như vậy:

class Account < ActiveRecord::Base 
    cattr_accessor :current 
end 

class ApplicationController < ActionController::Base 
    before_filter :set_current_account 
    def set_current_account 
    # set @current_account from session data here 
    Account.current = @current_account 
    end 
end 

Sau đó chỉ cần truy cập vào tài khoản vãng lai với Account.current

+11

Biến không phải là lớp được chia sẻ trên tất cả các yêu cầu ?! – vise

+0

Tôi không hiểu cách lấy giá trị biến từ biểu tượng: current trong mô hình? Tôi đã thử Account.current và hiện tại. – djburdick

+0

Sự khác nhau giữa 'cattr_accessor' và' attr_accessor' là gì? – user94154

1

Tôi không chắc chắn nếu tôi hiểu câu hỏi một cách chính xác, nhưng tôi sẽ mất một đâm. Tôi nghĩ nếu bạn cần truy cập một biến đối tượng điều khiển từ mô hình thì bạn cần phải biến nó thành một thuộc tính trong mô hình, hoặc chuyển logic của bạn sang bộ điều khiển lớp khác, chứ không phải mô hình.

5

Nếu bạn cần để truy cập một biến điều khiển từ một mô hình nó thường có nghĩa là thiết kế của bạn là sai bởi vì bộ điều khiển đóng vai trò như cầu nối giữa khung nhìn và mô hình (ít nhất là trong Rails), bộ điều khiển nhận thông tin từ mô hình, mô hình không biết gì về bộ điều khiển, nhưng nếu bạn muốn làm điều đó, bạn có thể làm như jeem nói, nhưng tôi muốn làm:

class << self 

    attr_accessor :current 

end 

thay vì

cattr_accessor :current

bạn có thể thấy lý do tại sao ở đây =>cattr_accessor doesn't work as it should

+0

Điều này không tốt hơn nhiều vì điều này vẫn được chia sẻ giữa các yêu cầu, để không nói gì về chủ đề an toàn. Nó phải là một thuộc tính trên User _instance_ hoặc nếu không bạn nên chuyển nó đến các phương thức cần biết nó. – gtd

2

Tôi không thể bình luận trực tiếp vì vậy tôi sẽ đăng ở đây: câu trả lời chấp nhận dường như không đúng. Như ghi chú @vise, các biến lớp được chia sẻ qua các yêu cầu. Vì vậy, trừ khi chỉ có một tài khoản hiện tại cho toàn bộ ứng dụng, điều này sẽ không hoạt động như mong đợi.

Để biết thêm, xem câu trả lời chấp nhận bởi @molf đây: Is Rails shared-nothing or can separate requests access the same runtime variables?

8

SỰ TỪ BỎ: Đoạn mã sau phá vỡ ước MVC, mà nói ...

Sử dụng thuộc tính lớp có lẽ có thể dẫn đến sợi an toàn vấn đề. Tôi sẽ sử dụng Thread.current + around_filter số liệu liên quan đến cửa hàng điều khiển ở cấp chủ đề, và đảm bảo nó được xóa ngay trước khi yêu cầu kết thúc:

class ApplicationController < ActionController::Base 

    around_filter :wrap_with_hack 

    def wrap_with_hack 
    # We could do this (greener solution): 
    # http://coderrr.wordpress.com/2008/04/10/lets-stop-polluting-the-threadcurrent-hash/ 
    # ... but for simplicity sake: 
    Thread.current[:controller] = self 
    begin 
     yield 
    ensure 
    # Prevent cross request access if thread is reused later 
    Thread.current[:controller] = nil 
    end 
    end 
end 

Bây giờ các trường hợp điều chỉnh dòng điện sẽ sẵn globaly trong quá trình xử lý yêu cầu thông qua Thread.current [: controller]

+0

Xin chào @ibaixas cảm ơn vì điều này. Nhưng bạn có thể giải thích làm thế nào thuộc tính lớp sẽ dẫn đến vấn đề an toàn thread. Tôi là một người mới. Và vấn đề này có trong Rails 4 cũng như – Akshat

+1

Biến lớp được chia sẻ giữa các luồng. Điều này có nghĩa là khi sử dụng một máy chủ ứng dụng đa luồng như puma, các luồng khác nhau xử lý các yêu cầu khác nhau sẽ lưu trữ cá thể bộ điều khiển trong cùng một biến, ghi đè lên nhau. Bằng cách sử dụng băm Thread.current bạn đảm bảo rằng biến chỉ được thiết lập bởi luồng hiện tại. Xin lỗi vì sự chậm trễ (2 năm) ... – ibaixas