2012-06-19 16 views
5

Ich habe ein Formular, das ich oben auf jeder Seite erscheinen möchte, also habe ich es in die Datei /app/views/layouts/application.html.erb aufgenommen und Ich erhalte den Fehler undefined method model_name 'für NilClass: Class` beim Versuch, die Seite zu laden.Rails undefinierte Methode `model_name 'für NilClass: Klasse

Hier ist die Form Schnipsel in application.html.erb

<%= form_for @user do |f| %> 
    <h3>Add new contact</h3> 
    <%= f.text_field :first_name %><br /> 
    <%= f.text_field :last_name %> 
    <%= f.text_field :email %> 
    <hr /> 
    <%= f.submit "Add Contact" %> 
<% end %> 

Hier ist meine /app/controllers/user_controller.rb

class UserController < ApplicationController 

    def index 

    end 

    def new 
     @user = User.new 
    end 

end 

Ich denke, dass ich diesen Fehler bin schlagen, weil da das formular in der application.html.erb-datei ist, muss ich irgendwie den pfad angeben, aber dann bin ich wieder sehr neu bei rails.

Lassen Sie mich wissen, wenn Sie etwas anderes gebucht haben.

EDIT Ola Vorschlag folgend, in meiner app/views/layout/application.html.erb Datei habe ich so etwas wie diese:

<div> 
<%= yield :add_user %> 
</div> 

und in meinem app/views/users/neu. html.erb Datei ich habe diese

<% content_for :add_user do %> 
    <%= form_for @user do |f| %> 
     <h3>Add new contact</h3> 
     First Name<br /> 
     <%= f.text_field :first_name %><br /> 
     Last Name<br /> 
     <%= f.text_field :last_name %><br /> 
     Email<br /> 
     <%= f.text_field :email %> 
     <hr /> 
     <%= f.submit "Add Contact" %> 
    <% end %> 
<% end %> 

die Form nicht wiedergegeben wird, weil meine url http://localhost:3000/admin/index ist und es so suchen die add_user content_for in app/views/admin/index.html.erb

+0

nehme ich an "wenn die Seite zu laden versuchen," Sie bedeuten '/ Benutzer' –

+0

Tut mir leid, ich lade diese Seite 'http: // localhost: 3000/admin/index' – Catfish

+0

Ja, ich dachte mir so viel, in dem obigen Beispiel'/users/new' sollte funktionieren (irgendwie), obwohl du ' Ich habe deine Ansichtsstruktur falsch verstanden - siehe meine Antwort unten. –

Antwort

12

Wenn das Formular für mehrere Aktionen (Seiten) enthalten ist, müssen Sie @user auf etwas setzen oder die form_for Richtlinie scheitern wird (es wird nichts haben eine Form für erstellen).

Ein wesentlich besserer Ansatz (und der Rails-Standard) besteht darin, für jede Aktion separate Ansichten zu haben, die jeweils nur die von dieser Aktion benötigten Elemente enthalten und in Ihr application.html.erb Layout mit <%= yield %> geladen werden. Sie hätten also eine app/views/users/new.html.erb Ansicht, die die Form darin hat. Sie nie sehr selten müssen Lastpfade in Rails definieren, sie sind alle von den Modell-, Controller-und Action-Namen abgeleitet - oder von Ihrem routes.rb. Dies ist ein Kernteil des Paradigmas, das so tief in Rails läuft.

Edit: Wenn Sie Notwendigkeit tun auf jeder Seite ein neues Objekt ein Formular haben für die Erstellung von (oft für UserSessions zum Beispiel verwendet wird), können Sie Ihre umschreiben form_for, so dass es nicht auf einem Objekt abhängt anwesend:

form_for(User.new) 

oder wenn Sie es brauchen dazu zu zwingen, die create Methode zu schreiben

form_for(User.new, :url => { :action => "create" }) 

Sie können mehr über r lesen esource driven form_for in Ruby On Rails API docs.

+0

Wenn Sie das Formular in app/views/users/new.html.erb einfügen, wird die Seite geladen, aber das Formular wird nicht mehr angezeigt. Ich habe meine Frage mit Details aktualisiert. – Catfish

+0

Ja, da ich nicht weiß, was Ihre Bedürfnisse sind, nahm ich einfach an, dass Sie eine Standard-CRUD-Seitenstruktur haben - siehe meine Bearbeitung oben, wenn Sie das Formular wirklich auf Seiten außerhalb des Benutzerbereichs haben müssen. –

+0

In diesem Fall würde ich das Formular in eine Teilansicht bringen (sagen wir '/ app/views/users/_inline_form.hmtl.erb') und lade es im' application.html.erb' Layout mit '<% ​​= render: partial => 'users/inline_form'%> '(beachten Sie das Fehlen des führenden" _ "). –

0

Ihr Problem ist, Sie versuchen, Formular zu jeder Aktion auf Ihrer Seite hinzufügen, aber Benutzer in allen Aktion nicht initialisiert.Versuchen Sie, den Benutzer in allen Aktionen zu initialisieren:

class UserController < ApplicationController 
    before_filter :initialize_user 

    def index 

    end 

    def initialize_user 
     @user = User.new 
    end 

end 
+2

Das wird nicht ganz funktionieren - da er das Formular in 'application.hmtl.erb 'hat, müsste er stattdessen den Code in ApplicationController einfügen, oder irgendeine Seite außerhalb des UserController-Bereichs würde immer noch den Fehler geben. Aber das ist akademisch; er hat seine Sichtstruktur in einem Gewirr und sollte umgestalten! –

+0

Ola ist genau richtig. Der Filter sollte sich im ApplicationController befinden, da er für jede Seite ausgeführt werden sollte. –

9

Haben Sie das Debuggen zuerst versucht? Ich frage, weil du sagst, dass du neu bei Rails bist. Wenn nicht, hier ist mein Ansatz. Ich möchte es teilen, weil ich überrascht bin, wie viele Leute (aus welchen Gründen auch immer) nicht sorgfältig debuggen.

(ich ein Test-App erstellt, so dass ich durch Ihr Problem gehen kann. Zuerst habe ich http://localhost:3000/users besucht.)

Zuerst wird in dem Stack-Trace aus.

NoMethodError in Benutzer # Index

/Users/david/dev/testapp/app/views/layouts/application.html.erb zeigt, wo Linie # 11 angehoben:

nicht definierte Methode ` model_name‘für NilClass: Klasse Extrahiert Quelle (um Zeile # 11):

8: </head> 
9: <body> 
10: 
11: <%= form_for @user do |f| %> 
12:  <h3>Add new contact</h3> 
13:  <%= f.text_field :first_name %><br /> 
14:  <%= f.text_field :last_name %> 

Diese Sie Zeile 11 in yo erzählt Dein Code ist das Problem. Denken Sie - was könnte das Problem sein? Routing ist unwahrscheinlich, da Sie nur die Seite rendern. Kein Syntaxfehler, der einen anderen Fehler ausgelöst hätte. Ok, so lesen Sie weiter:

Rails.root:/Users/david/dev/testapp

Anwendung Trace | Rahmenverfolgung | Voll Trace

Klicken Sie nun auf "Rahmen trace" und Sie werden sehen:

activemodel (3.2.6) lib/active_model/naming.rb: 163: in model_name_from_record_or_class' activemodel (3.2.6) lib/active_model/naming.rb:158:in param_key‘ Action (3.2. 6) lib/action_view/Helfer/form_helper.rb: 369: in `form_for‘

Sie können nicht verstehen, das alles - nur wenige Menschen tun - aber Sie werden sehen, der Fehler kommt von model_name_from_record_or_class, die aus param_key kommt was kommt aus form_for. Das ist ein großer Hinweis!

empfehle ich die Verwendung des open_gem Juwel, um es einfach in den Quellcode zu graben:

gem install open_gem 

nun einen Blick auf activemodel nehmen, da es das oberste Juwel in der Stack-Trace ist:

gem open activemodel 

Nun, die Suche nach diesem mit regulärem Ausdruck Benutzer aktiviert:

def * model_name_fro. m_record_or_class

(Warum? Sie möchten Klassenmethoden finden - z. Definitionen, die auch mit self beginnen.)

Dies bringt Sie zur Zeile 162 in naming.rb.

def self.model_name_from_record_or_class(record_or_class) 
    (record_or_class.is_a?(Class) ? record_or_class : convert_to_model(record_or_class).class).model_name 
end 

Auch ohne all dies zu verstehen, ist es ein großer Hinweis geben ... die Methode versucht, den Modellnamen aus dem Datensatz oder Klasse zurückzukehren. Warum kann es nicht? Da der übergebene Parameter @user nicht festgelegt wurde. Der Wert von nicht gesetzten Instanzvariablen ist Null, also wird es sich erst beschweren, wenn Sie versuchen, etwas damit zu tun.

Ich hoffe, dass dies für diese Frage und für die Zukunft hilft.

+0

hervorragende Anleitung zur Fehlerbehebung! –

6

Diese Antwort ist wirklich nur die Antwort von Someth korrigiert, aber die Lösung ist @user für jede Controller-Aktion, nicht nur diejenigen, die zu einem bestimmten Controller. Dies kann durch die Verwendung eines before_filter im Application, dh

class ApplicationController < ActionController::Base 
    before_filter :initialize_user 

    def initialize_user 
    @user = User.new 
    end 
end 

OR durch ein neues Modell in der form_for Helfer zu schaffen selbst (Anmerkung erfolgen: dies im Hinblick auf die Trennung von Bedenken hässlich ist, aber es funktioniert. ..)

<%= form_for User.new do |f| %> 
    <h3>Add new contact</h3> 
    <%= f.text_field :first_name %><br /> 
    <%= f.text_field :last_name %> 
    <%= f.text_field :email %> 
    <hr /> 
    <%= f.submit "Add Contact" %> 
<% end %> 
0

im Usercontroller:

def index 
    @user = User.new 
end 
Verwandte Themen