Elaborare la forma all'interno di un controller diverso


129

Sto usando una gemma ideata per le procedure sign_in / sign_out.

Ho generato i file delle viste da ideare, usando rails g devise views

Ho visto che c'era un file devise / sessioni / new.html.erb che conteneva un modulo per sign_in.

Ho creato un altro file devise / sessioni / _form.html.erb e fatto <%= render 'form' %>all'interno di un file new.html.erb, e ha funzionato molto bene.

Ora, volevo includere questo modulo dal diverso controller. Quindi in un controller chiamato 'main', (in particolare, all'interno della pagina di visualizzazione) 'mains / index.html.erb' ho incluso il <%= render 'devise/sessions/form' %>file. Sembra che l'inclusione abbia funzionato bene, ma sto ottenendo il seguente errore.

NameError in Mains#index

Showing /home/administrator/Ruby/site_v4_ruby/app/views/devise/sessions/_form.html.erb where line #1 raised:

undefined local variable or method `resource' for #<#<Class:0x007f1aa042d530>:0x007f1aa042b870>
Extracted source (around line #1):

1: <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
2:   <p><%= f.label :email %><br />
3:   <%= f.text_field :email %></p>
4: 

Sembra che la parte form_for (risorsa, ...) stia causando il problema (che funziona benissimo se mi trovo sulla pagina sign_in originale ideare ... Come posso risolvere questo problema in modo rotaia?

Personalmente preferisco usare la funzione 'render' per includere il modulo, piuttosto che scrivere codici HTML in linea.

Devo specificare qualcosa (risorsa) all'interno del controller 'principale'?

Apprezzerò il tuo aiuto. Grazie.


C'è qualche soluzione ...? A partire dal 16 novembre non ho davvero trovato la soluzione usando render .. anche se se
digito il

hai trovato una soluzione per questo?
Neebz,

Sì, ho scelto la risposta che risolve il mio problema. Era più semplice di quanto pensassi.
user482594,

Risposte:


241

Come dice Andres, il modulo chiama helper specificati da Devise e quindi non presenti quando si accede a un modulo Devise da un controller non Devise.

Per ovviare a questo, è necessario aggiungere i seguenti metodi alla classe di supporto del controller che si desidera visualizzare il modulo in. In alternativa, puoi semplicemente aggiungerli al tuo helper dell'applicazione per renderli disponibili ovunque.

  def resource_name
    :user
  end

  def resource
    @resource ||= User.new
  end

  def devise_mapping
    @devise_mapping ||= Devise.mappings[:user]
  end

Fonte: http://pupeno.com/blog/show-a-devise-log-in-form-in-another-page/


6
Eccellente. Assicurati che vada nell'aiutante, non nel controller. Inoltre, ciò potrebbe comportare enormi problemi se si dispone di altre risorse (ad esempio aziende che possono anche accedere) e si desidera caricare il loro modulo. Assicurati di ridefinire i nomi e anche il routing potrebbe diventare un problema.
Michael Schmitz,

1
La cosa negativa di questa soluzione è che si rompe inherited_resources.
jrhorn424,

6
Per limitare l'ambito di questi metodi (ed evitare conflitti dello spazio dei nomi con altre gemme, ad esempio), prova ad aggiungere i metodi sopra al controller stesso, insieme a helper_method :resource_name, :resource_class, :resource, :devise_mapping( :resource_classsembra essere un requisito nelle versioni più recenti di Devise).
parla il

1
Quale soluzione dovrebbe essere se abbiamo pochi modelli ideati?
yozzz,

Ho due modelli Devise e ho bisogno di accedere per entrambi sulla homepage. Qualche idea su come fare qualcosa di simile alla tua risposta?
DR_

8

Puoi provare anche questo ... controlla questa domanda .

fonte

<%= form_for("user", :url => user_session_path) do |f| %>
  <%= f.text_field :email %>
  <%= f.password_field :password %>
  <%= f.check_box :remember_me %>
  <%= f.label :remember_me %>
  <%= f.submit 'Sign in' %>
  <%= link_to "Forgot your password?", new_password_path('user') %>
<% end %> 

Non è questa la migliore pratica di tutte le risposte?
Allegutta,

4

Il modulo creato funziona quando viene eseguito il rendering da un controller Devise poiché "risorsa" è definita tramite Devise. Dai un'occhiata all'implementazione di Devise SessionsController - da quello che ho capito, stai tentando di replicare la "nuova" azione. Il metodo "build_resource" è probabilmente quello che stai cercando.

La gemma Warden è da dove provengono gli oggetti "risorsa". Se desideri scavare più a fondo, quello sarebbe il posto giusto dove cercare.


Ho appena chiamato 'build_resource' con in un mains_controller, ma richiama l'errore [variabile locale non definita o metodo `build_resource ']. Ho provato a includere l'helper interno escogitando inserendo "include Devise :: Controllers :: InternalHelpers" nella parte superiore di "mains_controller", ma viene anche visualizzato l'errore con "AbstractController :: ActionNotFound"
user482594

3

Per perfezionare la risposta accettata, utilizziamo questo aiuto per consentire diversi tipi di risorse:

def resource_name
  @resource_name ||= if admin_controller?
    :admin_user
  else
    :user
  end
end

def resource
  @resource ||= resource_name.to_s.classify.constantize.new
end

def devise_mapping
  @devise_mapping ||= Devise.mappings[resource_name]
end

dov'è admin_controller?qualcosa che abbiamo prima nel ApplicationControllergestire i reindirizzamenti di accesso:

def admin_controller?
  !devise_controller? and request.path =~ /^\/admin/
end
helper_method :admin_controller?

2

Stavo ottenendo lo stesso errore undefined local variable or method "resource"che descrivi da uno dei miei controller, perché nella mia classe base del controller mancava quanto segue (Rails-API ActionController :: API era in errore):

include ActionController::Helpers

Pertanto, i metodi di supporto di Devise non sono stati risolti nella vista.

Per far funzionare Devise con Rails-API dovevo includere:

class ApplicationController < ActionController::API

  include AbstractController::Rendering
  include AbstractController::Layouts
  include ActionController::MimeResponds
  include AbstractController::Translation
  include ActionController::ImplicitRender
  include ActionController::Helpers
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.