I have the following models, which basically try to mean that the professor has knowledge for many subjects for a certain level . Subjects are fixed, so new objects will not be created, they will simply be “connected” to the professor through a table of knowledge connections.
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
I want to have a form that allows the professor to add a topic to his account, and I decided to have a form for knowledge (since I also want to insert a level).
It looks like this:
<%= 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 %>
And in the create action of the Knowledges controller, I have the following:
def create @knowledge = Knowledge.create(:professor_id => current_professor.id, :subject_id => params[:knowledge][:subject_id]) end
I wanted / expected to get ActiveRecord saying that this knowledge cannot be inserted because there is a violation of uniqueness, but nops, I just see 500 in the logs and rollback, but it seems that the execution continues. Therefore, my question is: what am I doing wrong, or how could I improve this model situation? I believe that the form should be connected with the union model, because I want to have the fields of this model on it ... But maybe I'm wrong, and I could do it easily and simply.
EDIT
As indicated in one of the comments, here is the form submission log and 500 errors immediately after the 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
I added some conditions to the create action, for example:
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
And it actually shows right after 500:
Completed 500 Internal Server Error in 6ms ActiveRecord::RecordInvalid (Validation failed: Subject has already been taken):
I wonder why an exception occurs instead of just adding errors to the object and letting me manage this situation. Should the following line be followed?
validates :subject_id, :uniqueness => { :scope => :professor_id }