2009-10-16 8 views
16

Ich verwende Single Table Inheritance für die Verwaltung verschiedener Arten von Projekten.STI und Formular_für Problem

Modelle:

class Project < ActiveRecord::Base 
end 

class SiteDesign < Project 
end 

class TechDesign < Project 
end 

Aktion Bearbeiten von projects_controller:

def edit 
    @project = Project.find(params[:id]) 
end 

Ansicht edit.html.erb:

<% form_for(@project, :url => {:controller => "projects",:action => "update"}) do |f| %> 
    ... 
    <%= submit_tag 'Update' %> 
<% end %> 

Update-Aktion von projects_controller:

def update 
    @project = Project.find(params[:id]) 
    respond_to do |format| 
     if @project.update_attributes(params[:project]) 
     @project.type = params[:project][:type] 
     @project.save 
     flash[:notice] = 'Project was successfully updated.' 
     format.html { redirect_to(@project) } 
     format.xml { head :ok } 
     else 
     format.html { render :action => "edit" } 
     format.xml { render :xml => @project.errors, :status => :unprocessable_entity } 
     end 
    end 
    end 

Dann mache ich ein paar Änderungen von TechDesign Eintrag der Bearbeitungsansicht und erhalten Fehler:

NoMethodError in ProjectsController#update 

You have a nil object when you didn't expect it! 
You might have expected an instance of ActiveRecord::Base. 
The error occurred while evaluating nil.[] 

In parametrs es offensichtlich ist, dass anstelle Parameter Name des Projekts i Parameter tech_design haben:

{"commit"=>"Update", 
"_method"=>"put", 
"authenticity_token"=>"pd9Mf7VBw+dv9MGWphe6BYwGDRJHEJ1x0RrG9hzirs8=", 
"id"=>"15", 
"tech_design"=>{"name"=>"ech", 
"concept"=>"efds", 
"type"=>"TechDesign", 
"client_id"=>"41", 
"description"=>"tech"}} 

Wie etwas reparieren?

Antwort

27

Hier ist die Quelle Ihres Problems. Dadurch wird @project als Instanz eines TechDesign-Objekts festgelegt.

Sie können sicherstellen, dass die Dinge so funktionieren, wie Sie möchten, indem Sie Folgendes angeben: project für einen Namen in form_for call.

<% form_for(:project, @project, :url => {:controller => "projects",:action => "update"}) do |f| %> 
    ... 
    <%= submit_tag 'Update' %> 
<% end %> 
+0

Vielen Dank für Ihre Antwort. Nach diesen Chages habe ich diesen Fehler: Keine Aktion geantwortet 1. Aktionen: erstellen, zerstören, bearbeiten, indexieren, neu, anzeigen und aktualisieren – ebsbk

+1

Nach dem Hinzufügen dieser map.connect "projects /: id/edit", : controller => "projects",: action => "edit" zu routes.rb Fehler verschwunden. Die Frage ist, warum es ohne es nicht funktioniert, wenn map.resources: Projekte bereits in Routen präsentiert? – ebsbk

+11

In Schienen 3.1, schreibe die form_for-Anweisung als <% = form_for @project,: as =>: project do | f | %> – Cygwin98

2

Eine zufällige Anmerkung: Wenn Sie einzelne Tabelle Vererbung (STI) und vergessen werden mit den initialisieren Methode aus der Unterklasse Definitionen entfernen erhalten Sie ein ähnliches „Null-Objekt, wenn man es nicht erwartet hat“ bekommen Ausnahme.

Zum Beispiel:

class Parent < ActiveRecord::Base 
end 

class Child < Parent 
    def initialize 
    # you MUST call *super* here or get rid of the initialize block 
    end 
end 

In meinem Fall habe ich meine IDE die untergeordneten Klassen zu erstellen und die IDE die initialize-Methode erstellt. Hat mich immer auf die Spur ...

6

Für Rails 3

<% form_for(@project, :as => :project, :url => {:controller => "projects",:action => "update"}) do |f| %> 
... 
    <%= submit_tag 'Update' %> 
<% end %> 
1

Für Rails 4 habe ich das einzige, was bestätigt, dass für mich schien hat zu arbeiten, ist explizit die URL angeben, und die AS Parameter:

<% form_for(@project, as: :project, url: {controller: :projects, action: :update}) do |f| %> 
    ... 
<% end %> 

Scheint hässlich zu mir!