2009-08-17 11 views
8

Próbowałem objąć głowę render_to, ale nie odniosłem dużego sukcesu.Jak mogę przekazywać obiekty z jednego kontrolera do drugiego w szynach?

Zasadniczo mam metod kontrolera:

def first 
    #I want to get the value of VAR1 here 
end 

def second 
    VAR1 = ["Hello", "Goodbye"] 
    render_to ?? 
end 

Nie mogę wymyślić sposób, aby tego dokonać. Pierwotnie chciałem renderować plik first.html.erb, ale to też nie działa.

Dzięki

EDIT: Doceniam odpowiedzi otrzymałem, jednak wszystkie z nich wydają się unikać stosowania tynku metodę lub redirect_to. Czy to w zasadzie wtedy, gdy nie można przekazać zmiennych z kontrolera do kontrolera? Muszę myśleć, że jest jakiś sposób, ale nie mogę tego znaleźć.

Odpowiedz

20

Nie jest dobrym pomysłem przypisanie obiektu do stałej. To prawda, że ​​jest to przestrzeń globalna, ale jest ona globalna dla każdego, więc każdy inny użytkownik, który zgłosi się na tę prośbę, otrzyma ten obiekt. Istnieje kilka rozwiązań w tym zakresie.

Zakładam, że masz wieloetapową formę, przez którą przechodzisz. W takim przypadku możesz przekazać ustawione atrybuty jako ukryte pola.

<%= f.hidden_field :name %> 

Jeśli istnieje wiele pól może to być uciążliwe, więc może chcesz pętli metody params[...] hash lub column_names w celu określenia, które atrybuty do przejścia.

Alternatywnie można przechowywać atrybuty w session.

def first 
    @item = Item.new(params[:item]) 
    session[:item_attributes] = @item.attributes 
end 

def second 
    @item = Item.new(session[:item_attributes]) 
    @item.attributes = params[:item] 
end 

Po trzecie, jak Paul Keeble wymienić można zapisać model do bazy danych, ale oznaczyć go jako niekompletny. Możesz użyć do tego celu state machine.

Wreszcie, możesz rzucić okiem na Acts As Wizard plugin.

+0

Witaj Ryan, czy opcja sesji jest nadal ważna w Railsach 3? Jeśli przechowuję '@ item.attributes', przechowuje on chronione atrybuty, takie jak id i timestamps jako zero, próba zbudowania nowego obiektu z tej sesji później skutkuje błędem MassAssignmentSecurity – Noz

+0

' object.attributes.slice ('field1', 'field2') 'wydaje się być sposobem, aby po prostu zastąpić field1 i field2 z dowolnymi polami są potrzebne. – Noz

+0

Awesome Ryan Szukałem tej odpowiedzi przez długi czas !!! – Cas

2

Zazwyczaj nie mam kontrolerów nawołujących do nawzajem swoich działań. Jeśli masz identyfikator zaczynający się od dużej litery, w Ruby jest stała. Jeśli chcesz mieć zmienną poziomu instancji, zacznij od @.

@var1 = ["Hello", "Goodbye"] 

Czy możesz wyjaśnić, jaki jest twój cel?

+0

Zasadniczo próbuję wykonać wieloetapowy proces, w którym użytkownik przesyła plik, następnie przetwarzam go i ponownie go przedstawiam, aby mógł wprowadzić w nim pewne zmiany, a następnie włożyć go do bazy danych. Aby to zrobić, muszę mieć możliwość przekazania tego obiektu do innego kontrolera lub co najmniej innego widoku kontrolerów. –

+0

Zamiast tego, nie przechowuj wyników pośrednich swoich działań w bazie danych i nie oznaczaj jako niekompletne. W ten sposób wiesz, że masz do niego dostęp poprzez model jak zwykle i jesteś odporny na awarie serwerów. –

2

Czy zastanawiałeś się nad użyciem skrótu flash? Wiele osób używa go wyłącznie do komunikatów o błędach i tym podobnych. Jest to wyraźnie rodzaj przejściowych danych, które mogą Cię zainteresować.

Zasadniczo metoda flash zwraca skrót. Każda wartość przypisana do klucza w haszdzie będzie dostępna dla następnej akcji, ale potem zniknie.Więc:

def first 
    flash[:var] = ["hello", "goodbye"] 
    redirect_to :action => :second 
end 

def second 
    @hello = flash[:var].first 
end 
2
  1. sposób 1
    zmienna globalna (nie podczas jednoczesnych żądań)
  2. sposób 2
    klasy zmiennej (nie podczas jednoczesnych żądań)
  3. drogę 3

    • Schowaj obiekt na serwerze między żądaniami. Typowym sposobem jest zapisanie go w sesji, ponieważ automatycznie serializuje/deserializuje obiekt dla ciebie.
    • Serializuj obiekt i dołącz go gdzieś do formularza, a następnie przekształć go z postaci szeregowych w następnym żądaniu. dzięki czemu można przechowywać atrybuty w sesji.

       
      def first 
      @item = Item.new(params[:item]) 
      session[:item_attributes] = @item.attributes 
      end 
      
      def second 
      @item = Item.new(session[:item_attributes]) 
      @item.attributes = params[:item] 
      end 
      
  4. sposób 4
    błyskowa zapewnia sposób przekazać tymczasowych obiektów pomiędzy działaniami. Wszystko, co umieścisz w lampie błyskowej, zostanie wystawione na następną akcję, a następnie usunięte.
     
    def new 
        @test_suite_run = TestSuiteRun.new 
        @tests = Test.find(:all, :conditions => { :test_suite_id => params[:number] }) 
        flash[:someval] = params[:number] 
    end 
    def create
    @test_suite_run = TestSuiteRun.new(params[:test_suite_run]) @tests = Test.find(:all, :conditions => { :test_suite_id => flash[:someval] })
    end
  5. sposób 5
    można użyć szyny pamięci podręcznej.

     
        Rails.cache.write("list",[1,2,3]) 
        Rails.cache.read("list") 
    
    Co się dzieje, gdy różne sesje mają różne wartości? Chyba zapewnić unikalność nazwy listy całej sesji to rozwiązanie zawiedzie podczas jednoczesnych żądań

  6. sposób 6
    W jednym sklepie działania wartość w tabeli db na podstawie identyfikatora sesji i innych działań może pobrać go z db na podstawie identyfikatora sesji.

  7. sposób 7

     
    class BarsController < UsersController
    before_filter :init_foo_list

    def method1 render :method2 end

    def method2 @foo_list.each do | item| # do something end end

    def init_foo_list @foo_list ||= ['Money', 'Animals', 'Ummagumma'] end end

  8. sposób 8
    Od działań wysłane do przeglądania i ponownie z widokiem wysłanym do innych działań w kontrolerze.

Powiązane problemy