2012-06-30 16 views
7

ho i seguenti modelli, che sostanzialmente stanno cercando di dire che un professore ha conoscenze di molti soggetti per un particolare livello di . I soggetti sono fissi, quindi non ci saranno nuovi soggetti creati, ci sarà solo "collegato" ad un professore attraverso la tabella di conoscenza.Rails: Unicità di due attributi Registrazione tavolo causando 500 errore

class Subject < ActiveRecord::Base 
    # Self Associations 
    has_many :subcategories, :class_name => "Subject" 
    belongs_to :category, :class_name => "Subject",:foreign_key => "parent_id" 

    # Associations 
    has_many :knowledges 
    has_many :professors, :through => :knowledges 
end 


class Professor < ActiveRecord::Base 
    # Associations 
    has_many :knowledges 
    has_many :subjects, :through => :knowledges 
    ... 
end 

class Knowledge < ActiveRecord::Base 
    # Associations 
    belongs_to :professor 
    belongs_to :subject 
    has_one :level 

    attr_accessible :subject_id, :professor_id 

    validates :subject_id, :uniqueness => { :scope => :professor_id } 
end 

voglio avere una forma che permette un professore ad aggiungere un oggetto al suo conto, e ho deciso di avere una forma di conoscenza (come io voglio essere in grado di inserire un livello troppo).

Ecco come si presenta:

<%= simple_form_for @knowledge,:url => professor_knowledges_path, :html => { :class => 'form-horizontal' } do |f| %> 
    <div class="control-group select optional"> 
     <%= label_tag "Subject Type", nil, :class => "select optional control-label"%> 
     <div class="controls"> 
    <%= select_tag "Parent Subject", options_from_collection_for_select(@parent_subjects, "id", "name"), :id => "knowledge_parent_subject" %> 
     </div> 
    </div> 
    <%= f.input :subject_id, :collection => @subjects, :label => "Subject" %> 
    <%= f.input :level %> 
    <%= f.button :submit, t('add_form'),:class => 'btn-primary' %> 
<% end %> 

E nel creare del regolatore Conoscenze ho questo:

def create 
    @knowledge = Knowledge.create(:professor_id => current_professor.id, :subject_id => params[:knowledge][:subject_id]) 
    end 

Vorrei/si aspettano di ottenere un ActiveRecord dicendo che questa conoscenza non può essere inserita perché c'è una violazione di unicità, ma nops, vedo solo un 500 nei registri e un rollback, ma sembra che l'esecuzione continui. Quindi la mia domanda è: cosa sto sbagliando, o come potrei migliorare questa situazione di modellazione? Credo che la forma debba essere correlata al modello di join in quanto voglio avere campi di quel modello su di esso ... Ma forse mi sbaglio e potrei farlo in un modo facile/pulito.

EDIT:

Come chiesto in uno dei commenti, qui è il registro della presentazione della forma e l'errore 500 subito dopo il rollback:

Started POST "/professors/1/knowledges" for 127.0.0.1 at 2012-07-01 00:45:39 -0700 
Processing by KnowledgesController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"4JVyxWnIh37kyBwLwLGTHk/znsI1c5wrJvaWjKKT5tM=", "Parent Subject"=>"1", "knowledge"=>{"subject_id"=>"1"}, "commit"=>"Añadir", "professor_id"=>"1"} 
    Professor Load (0.4ms) SELECT `professors`.* FROM `professors` WHERE `professors`.`id` = 1 LIMIT 1 
Completed 500 Internal Server Error in 4ms 

ho aggiunto alcune condizioni nel creare azione, in questo modo:

def create 
    @knowledge = Knowledge.new(:professor_id => current_professor.id, :subject_id => params[:knowledge][:subject_id]) 
    if @knowledge.save 
     flash[:notice] = "Success..." 
     redirect_to professor_path(current_professor) 
    else 
     render :action => 'new' 
    end 
    end 

E questo in realtà mostrano s il seguente subito dopo il 500:

Completed 500 Internal Server Error in 6ms 

ActiveRecord::RecordInvalid (Validation failed: Subject has already been taken): 

mi chiedo il motivo per cui l'eccezione viene sollevata invece di aggiungere gli errori in oggetto e lasciare che a gestire quella situazione. Non è quello che dovrebbe fare la seguente riga?

validates :subject_id, :uniqueness => { :scope => :professor_id } 
+0

Si prega di inviare i registri che portano a 500. Sarebbe utile. I log – prasvin

+0

sono stati registrati :) – Nobita

+0

Sì, gli errori dovrebbero essere stati aggiunti all'oggetto. Non penso che stia causando l'errore 500. Puoi interrompere l'esecuzione prima che la riga 'if @ knowledge.save' in KnowledgesController # crei, usando il debugger o la leva. Quindi prova '@ knowledge.save' e' @ knowledge.save! 'Solo per confermare che gli errori di validazione sono stati incorporati in' @ knowledge'. Potresti verificarlo anche dalla console. Inoltre, è possibile pubblicare un sommario dell'intera traccia dello stack. Ho la forte sensazione che ciò non sia dovuto alla convalida dell'unicità. – prasvin

risposta

0

Tale errore significa che si sta tentando di inserire duplicati subject_id/professor_id coppie su quel tavolo. Molto spesso accade quando lo subject_id o professor_id è null.

Sei sicuro che il controller ha i parametri corretti? Vorrei controllare i registri per assicurarmi che gli inserti fossero ciò che ti aspetteresti.

0

io non ho abbastanza fama di commentare ... la mia risposta è più alcune cose da provare che una risposta definitiva, mi dispiace.

Sembra che il salvataggio non sia riuscito a causa di errori di convalida. Puoi provare a gestire quelli nel tuo blocco 'else'. Quanto segue ti fornirà una descrizione di tutti gli errori di validazione (utile per il debug).

@knowledge.errors.full_messages 

Non hai mostrato cosa sta succedendo nella 'nuova' azione. Sospetto che sia qui che si verificano gli errori.

Si verifica lo stesso problema (vale a dire il problema di convalida) nella console?In tal caso, provare a pulire i database (attenzione: il seguente comando cancellerà & ricostruire tutti i database).

rake db: goccia: tutti i db: creare: tutto db: migrate db: prova: preparare

Inoltre, se non l'hai già fatto, aggiungere un indice per la migrazione per conoscenza a prevenire duplicati aggiunti al db. per esempio.

add_index :knowledges, [ :professor_id, :subject_id ], unique: true