2010-03-10 16 views
19

Próbuję uzyskać dostęp do zmiennej instancji, która jest ustawiona w kontrolerze w modelu. Kontroler to kontroler produktów, a model to model produktów. Zmienna instancji jest instancją innego modelu o nazwie account.Ruby on Rails - zmienna kontrolera dostępu z modelu

Zmienna instancji jest @current_account

Kiedy uruchomić kod dzieje się nic, nie pojawia się błąd. Czy ktoś wie, gdzie mogę znaleźć coś czytać o dostępie do zmiennych instancji ustawionych w kontrolerze z modelu?

Dzięki

Eef

+0

Próbujesz uzyskać dostęp do zmiennej @current_account w modelu? Zmienna @current_account jest ustawiana w kontrolerze? – Steve

Odpowiedz

46

Powinieneś zasadniczo nie próbować uzyskać dostępu do kontrolera z modelu w przypadku problemów o wysokim mniemaniu, do których nie wejdę.

I rozwiązać podobny problem tak:

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 

Następnie wystarczy otworzyć rachunek bieżący Account.current

+11

Czy zmienne klasowe nie są wspólne dla wszystkich wniosków ?! – vise

+0

Nie rozumiem, jak uzyskać wartość zmiennej z: bieżącego symbolu w modelu? Próbowałem Account.current i current. – djburdick

+0

Jaka jest różnica między 'cattr_accessor' i' attr_accessor'? – user94154

1

Nie jestem pewien, czy rozumiem dokładnie to pytanie, ale wezmę ukłucie.

Myślę, że jeśli potrzebujesz uzyskać dostęp do zmiennej instancji kontrolera z modelu, musisz albo uczynić ją atrybutem w modelu, albo przenieść logikę do innego kontrolera klasy, a nie modelu.

5

Jeśli potrzeba dostęp do zmiennej kontrolera z modelu to zazwyczaj oznacza, że ​​projekt jest źle, ponieważ kontroler służy jako pomost między widokiem a modelem (przynajmniej w Railsach), kontroler pobiera informacje z modeli, modele nie powinny nic wiedzieć o kontrolerach, ale jeśli chcesz to zrobić, możesz to zrobić tak jak powiedział jeem, ale wolę zrobić:

class << self 

    attr_accessor :current 

end 

zamiast

cattr_accessor :current

można zobaczyć, dlaczego tutaj =>cattr_accessor doesn't work as it should

+0

Nie jest to dużo lepsze, ponieważ jest nadal dzielone między prośby, aby nic nie mówić o bezpieczeństwie wątków. Powinien to być atrybut na User _instance_ lub też przekazać go metodom, które muszą go znać. – gtd

2

nie mogę wypowiedzieć się bezpośrednio więc będę pisać tutaj: zaakceptowana odpowiedź nie wydaje się być w porządku. Jak zauważa @vise, zmienne klasy są współużytkowane dla żądań. Więc jeśli nie ma tylko jednego konta bieżącego dla całej aplikacji, nie będzie to działać zgodnie z oczekiwaniami.

Aby uzyskać więcej, zobacz odpowiedź zaakceptowana przez @molf tutaj: Is Rails shared-nothing or can separate requests access the same runtime variables?

8

Uwaga: Poniższy kod łamie konwencje MVC, który powiedział ...

Używanie atrybutów klasy może prawdopodobnie prowadzić do wątku bezpieczeństwa problemy. użyłbym Thread.current + around_filter do danych związanych z kontrolera magazynu na poziomie wątku, i upewnić się, że zostanie wyczyszczone tuż przed żądanie kończy:

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 

Teraz bieżąca instancja kontrolera będzie dostępna globalnie w czasie przetwarzania żądania przez Thread.current [: controller]

+0

Cześć @ibaixas dziękuję za to. Ale czy możesz wyjaśnić, w jaki sposób atrybut klasy prowadzi do kwestii bezpieczeństwa wątków. Jestem nowicjuszem. I czy ten problem występuje również w Railsach 4, a także – Akshat

+1

Zmienne klasy są współużytkowane przez wątki. Oznacza to, że podczas używania wielowątkowego serwera aplikacji, takiego jak puma, różne wątki obsługujące różne żądania będą przechowywać instancję kontrolera w tej samej zmiennej, zastępując siebie nawzajem. Używając skrótu Thread.current, upewnij się, że zmienna jest ustawiona tylko przez bieżący wątek. Przepraszamy za opóźnienie (2 lata) ... – ibaixas