Entwickeln Sie ein Formular in einem anderen Controller


128

Ich verwende ein Juwel für sign_in / sign_out-Prozeduren.

Ich habe Views-Dateien von devise mit generiert rails g devise views

Ich habe gesehen, dass es eine Datei devise / session / new.html.erb gibt, die ein Formular für sign_in enthält.

Ich habe eine andere Datei devise / session / _form.html.erb erstellt und dies <%= render 'form' %>in einer new.html.erb-Datei getan, und das hat sehr gut funktioniert.

Jetzt wollte ich dieses Formular von den verschiedenen Controllern einfügen. Also habe ich in einem Controller namens 'main' (speziell innerhalb der Ansichtsseite) 'mains / index.html.erb' eine <%= render 'devise/sessions/form' %>Datei eingefügt . Es scheint, dass die Aufnahme gut funktioniert hat, aber ich erhalte den folgenden Fehler.

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: 

Es scheint, dass der Teil form_for (resource, ...) das Problem verursacht (was gut funktioniert, wenn ich mich auf der ursprünglichen Anmeldeseite des Geräts befinde ... Wie kann ich dieses Problem auf Schienen lösen?

Ich persönlich bevorzuge die Verwendung der Renderfunktion, um das Formular einzuschließen, anstatt HTML-Codes inline zu schreiben.

Muss ich im Hauptcontroller etwas (Ressource) angeben?

Ich werde Ihre Hilfe schätzen. Danke dir.


Gibt es eine Lösung ...? Ab dem 16. November habe ich die Lösung mit Render nicht wirklich. Obwohl ich nur Inline-Code
eingebe

Hast du eine Lösung dafür gefunden?
Neebz

Ja, ich habe die Antwort gewählt, die mein Problem löst. Es war einfacher als ich gedacht hatte.
user482594

Antworten:


240

Wie Andres sagt, ruft das Formular Helfer auf, die von Devise angegeben wurden und daher nicht vorhanden sind, wenn Sie von einem Nicht-Devise-Controller auf ein Devise-Formular zugreifen.

Um dies zu umgehen, müssen Sie der Hilfsklasse des Controllers, unter dem Sie das Formular anzeigen möchten, die folgenden Methoden hinzufügen. Alternativ können Sie sie einfach zu Ihrem Anwendungshelfer hinzufügen, um sie überall verfügbar zu machen.

  def resource_name
    :user
  end

  def resource
    @resource ||= User.new
  end

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

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


6
Ausgezeichnet. Stellen Sie sicher, dass es in den Helfer geht, nicht in die Steuerung. Dies kann auch zu großen Problemen führen, wenn Sie über andere Ressourcen verfügen (z. B. Unternehmen, die sich ebenfalls anmelden können) und deren Formular laden möchten. Stellen Sie sicher, dass Sie die Namen neu definieren, und das Routing kann ebenfalls zu einem Problem werden.
Michael Schmitz

1
Das Schlechte an dieser Lösung ist, dass sie kaputt geht inherited_resources.
jrhorn424

6
Um den Umfang dieser Methoden einzuschränken (und beispielsweise Namespace-Konflikte mit anderen Edelsteinen zu vermeiden), versuchen Sie, die oben genannten Methoden zusammen mit dem Controller selbst hinzuzufügen helper_method :resource_name, :resource_class, :resource, :devise_mapping(dies :resource_classscheint in neueren Devise-Versionen erforderlich zu sein).
Spume

1
Welche Lösung sollte es sein, wenn wir nur wenige Modelle haben?
Yozzz

Ich habe zwei Devise-Modelle und muss mich für beide auf der Homepage anmelden. Haben Sie eine Idee, wie Sie etwas Ähnliches wie Ihre Antwort tun können?
DR_

8

Kann das auch versuchen ... überprüfe diese Frage .

Quelle

<%= 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 %> 

Ist dies nicht die beste Vorgehensweise aller Antworten?
Allegutta

4

Das von Ihnen erstellte Formular funktioniert beim Rendern von einem Devise-Controller, da "Ressource" über Devise definiert wird. Schauen Sie sich die Implementierung des Devise SessionsController an. Soweit ich weiß, versuchen Sie, die "neue" Aktion zu replizieren. Die Methode "build_resource" ist wahrscheinlich das, wonach Sie suchen.

Der Warden- Edelstein ist der Ort, von dem die "Ressourcen" -Objekte stammen. Wenn Sie tiefer graben möchten, ist dies der richtige Ort für Sie.


Ich habe gerade 'build_resource' mit in einem mains_controller aufgerufen, aber es ruft den Fehler [undefinierte lokale Variable oder Methode `build_resource '] auf. Ich habe versucht, den internen Helfer von devise einzuschließen, indem ich 'include Devise :: Controllers :: InternalHelpers' oben in den 'mains_controller' eingefügt habe, aber es wird auch ein Fehler mit 'AbstractController :: ActionNotFound'
user482594

3

Um die akzeptierte Antwort zu verfeinern, verwenden wir diesen Helfer, um verschiedene Arten von Ressourcen zuzulassen:

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

wo admin_controller?ist etwas , das wir aus , bevor sie in die haben ApplicationControllerzu Griff Login Umleitungen:

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

2

Ich habe den gleichen Fehler erhalten, den undefined local variable or method "resource"Sie von einem meiner Controller beschrieben haben, weil in meiner Controller-Basisklasse Folgendes fehlte (Rails-API ActionController :: API war fehlerhaft):

include ActionController::Helpers

Daher konnten die Hilfsmethoden von Devise in der Ansicht nicht aufgelöst werden.

Damit Devise mit der Rails-API funktioniert, musste ich Folgendes einschließen:

class ApplicationController < ActionController::API

  include AbstractController::Rendering
  include AbstractController::Layouts
  include ActionController::MimeResponds
  include AbstractController::Translation
  include ActionController::ImplicitRender
  include ActionController::Helpers
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.