Rails:连接表中两个属性的唯一性导致500错误

Nob*_*ita 7 model validates-uniqueness-of jointable ruby-on-rails-3

我有以下模型,这些模型基本上试图表示教授对特定级别的许多科目有所了解.主题是固定的,因此不会创建新的主题,通过知识连接表只会与教授"相关".

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
Run Code Online (Sandbox Code Playgroud)

我希望有一个表格可以让教授在他的帐户中添加一个主题,我决定有一个知识形式(因为我希望能够插入一个级别).

它看起来像这样:

<%= 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 %>
Run Code Online (Sandbox Code Playgroud)

在Knowledges控制器的创建动作中,我有:

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

我希望/期望得到一个ActiveRecord说这个知识无法插入,因为存在唯一性违规,但是nops,我只看到日志中的500和回滚,但似乎执行继续.所以我的问题是:我做错了什么,或者我如何改进这种建模情况?我认为表单需要与连接模型相关,因为我想在其上设置该模型的字段......但也许我错了,我可以用简单/清洁的方式做.

编辑:

正如其中一条评论中所述,这里是回滚后提交表单和500错误的日志:

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
Run Code Online (Sandbox Code Playgroud)

我在create动作中添加了一些条件,如下所示:

  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
Run Code Online (Sandbox Code Playgroud)

这实际上在500之后显示以下内容:

Completed 500 Internal Server Error in 6ms

ActiveRecord::RecordInvalid (Validation failed: Subject has already been taken):
Run Code Online (Sandbox Code Playgroud)

我想知道为什么会引发异常,而不是仅仅将错误添加到对象中,让我管理这种情况.不是以下行应该做什么?

validates :subject_id, :uniqueness => { :scope => :professor_id }
Run Code Online (Sandbox Code Playgroud)

Tan*_*ili 0

该错误意味着您正在尝试在该表上插入重复subject_id/professor_id对。最常发生在 或subject_idprofessor_idnull

您确定控制器获取了正确的参数吗?我会检查日志以确保插入内容符合您的预期。