Rails在has_and_belongs_to_many中更改表名

时间:2017-02-07 02:57:39

标签: ruby-on-rails activerecord sqlite

我有两个模型StageBatchStageItem

class StageItem < ApplicationRecord
  has_and_belongs_to_many :stage_batches
end

class StageBatch < ApplicationRecord
  has_and_belongs_to_many :stage_items
end

通过以下迁移:

class CreateStageBatchesAndStageItems < ActiveRecord::Migration[5.0]
  def change
    create_table :stage_items do |t|
      t.string :name
      t.timestamps
    end

    create_table :stage_batches do |t|
      t.timestamps
    end

    create_table :stage_batches_and_stage_items, id: false do |t|
      t.belongs_to :stage_item, index: true
      t.belongs_to :stage_batch, index: true
    end
  end
end

当我尝试访问stage_batches stage_items时,出现以下错误:

irb(main):002:0> StageBatch.first.stage_items
  StageBatch Load (0.2ms)  SELECT  "stage_batches".* FROM "stage_batches" ORDER BY "stage_batches"."id" ASC LIMIT ?  [["LIMIT", 1]]
  StageItem Load (0.4ms)  SELECT "stage_items".* FROM "stage_items" INNER JOIN "stage_batches_items" ON "stage_items"."id" = "stage_batches_items"."stage_item_id" WHERE "stage_batches_items"."stage_batch_id" = ?  [["stage_batch_id", 1]]
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such table: stage_batches_items: SELECT "stage_items".* FROM "stage_items" INNER JOIN "stage_batches_items" ON "stage_items"."id" = "stage_batches_items"."stage_item_id" WHERE "stage_batches_items"."stage_batch_id" = ?
  • 我的迁移有问题吗?
  • 命名约定有问题吗?
  • 为什么我的表格的名称从stage_batches_and_stage_items变为` 我的迁移有问题吗?
  • 命名约定有问题吗?为什么我的表格的名称似乎从stage_batches_and_stage_items更改为stage_batches_items

1 个答案:

答案 0 :(得分:0)

在使用has_and_belongs_to_many时,您必须遵循Rails命名约定来命名连接表。或者,您可以使用join_table选项指定连接表名称。

在您的特定情况下,将stage_batches_and_stage_items的名称更改为stage_batches_stage_items。默认情况下,连接表以词法顺序具有两个表名(复数形式)。

来自Rails guide [Section 3.3.2]

  

如果您创建了has_and_belongs_to_many关联,则需要   显式创建连接表。除非连接表的名称   通过使用:join_table选项Active Record明确指定   通过使用类名的词汇书来创建名称。那么一个   作者和书籍模型之间的连接将给出默认的连接表   &#34; authors_books&#34;的名称因为&#34; a&#34;超支&#34; b&#34;在词汇排序中。

如果由于它的限制(例如,您无法在此加入表中添加任何额外的列),我建议避免使用has_and_belongs_to_many(如果这不是一个严格的要求)。相反,请使用{ {3}}关联。在这种情况下,您可以轻松自定义连接的表名称。此外,您可以根据需要在连接表中添加额外的列。

以下是使用has_many :through关联代码的方式:

class StageItem < ApplicationRecord
  has_many :stage_item_batches
  has_many :stage_batches, through: :stage_item_batches
end

# joining model
class StageItemBatch < ApplicationRecord
  belongs_to :stage_item
  belongs_to :stage_batch
end

class StageBatch < ApplicationRecord
  has_many :stage_item_batches
  has_many :stage_items, through: :stage_item_batches
end

原始两个模型的迁移将保持不变。您只需要迁移加入模型:

rails g model StageItemBatch stage_item:references stage_batch:references