5

我有 A 型和 B 型;A has_many B, and B belongs_to A. 到目前为止,一切都很好——除了,我指定 B 没有主键。我不打算修改或删除单独的 B 行,我希望有几百万到十亿个,所以省略主键将非常方便,空间方面。

创建 B 表的迁移如下所示:

class CreateBs < ActiveRecord::Migration
  def change
    create_table :bs, {:id => false} do |t|
      # … rest of fields …
    end
  end
end

不幸的是,ActiveRecord 不同意。尝试创建 A(没错!)会导致:

1.9.3p194 :001 > A.create!
   (0.3ms)  BEGIN
   (0.1ms)  ROLLBACK
ActiveRecord::UnknownPrimaryKey: ActiveRecord::UnknownPrimaryKey
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/reflection.rb:366:in `primary_key'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/reflection.rb:216:in `association_primary_key'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/has_many_association.rb:104:in `foreign_key_present?'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/association.rb:165:in `find_target?'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_association.rb:332:in `load_target'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_proxy.rb:44:in `load_target'
…

如果你捕捉到异常,它的message状态:

"Unknown primary key for table bs in model B." 

(这是因为 B 没有主键。)

我不想有这个问题!有什么办法吗?

4

2 回答 2

3

罪魁祸首原来是问题中遗漏的一个细节——当然——以及我的工作记忆中遗漏的细节:

class A < ActiveRecord::Base
  has_many :bs

  validates :bs, :presence => true
end

尽管当时我对此一无所知,但在许多其他验证中,有一个验证bs. 如果您对完整的回溯非常仔细地眯起眼睛——我在最初的问题中“有帮助”足以截断,您会看到:

ActiveRecord::UnknownPrimaryKey: ActiveRecord::UnknownPrimaryKey
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/reflection.rb:366:in `primary_key'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/reflection.rb:216:in `association_primary_key'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/has_many_association.rb:104:in `foreign_key_present?'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/association.rb:165:in `find_target?'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_association.rb:332:in `load_target'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_proxy.rb:44:in `load_target'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_proxy.rb:87:in `method_missing'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/errors.rb:255:in `block in add_on_blank'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/errors.rb:253:in `each'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/errors.rb:253:in `add_on_blank'
        from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/validations/presence.rb:8:in `validate'
-------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^

错误发生在active_model/validations/presence.rb!消除这个约束就足以让我们继续前进。它找不到验证的目标,因为它试图使用主键来这样做,因此失败了。

于 2012-08-21T09:04:47.950 回答
1

嗯,这很奇怪。出于某种原因,鉴于您发布的信息,我无法复制我的问题。我创建了一个新项目,创建了一个 A 模型,然后创建了一个引用 A 的 B 模型,然后运行了迁移。正如预期的那样,我的 B 表没有主键,只有 A 的外键。

我唯一可以建议的是以下

像这样编写您的 A 模型:

class A < ActiveRecord::Base
  has_many :b, :primary_key=>:myPrimaryKeyFunction # name this function whatever you want, other than :id of course
end

然后,在 B 模型中,简单地创建相应的“myPrimaryKeyFunction”函数。

除此之外,我不确定还有什么建议。您正在运行什么版本的 Rails 和哪个数据库?

于 2012-08-20T21:10:40.737 回答