Rails:在命名空间中的两个模型之间创建多对多关系需要做些什么?

rod*_*amn 1 activerecord many-to-many namespaces has-and-belongs-to-many ruby-on-rails-4

命名空间中有两个模型,它们需要与has_and_belongs_to_many以多对多关系关联.它们是这样创建的:

$ rails generate model namespace/model_a name:string

# app/models/namespace/model_a.rb
class Namespace::ModelA < ActiveRecord::Base
end
Run Code Online (Sandbox Code Playgroud)

$ rails generate model namespace/model_b name:string

# app/models/namespace/model_b.rb
class Namespace::ModelB < ActiveRecord::Base
end
Run Code Online (Sandbox Code Playgroud)

我需要做什么才能成功建立多对多关系?

rod*_*amn 5

我有很多问题要解决这个问题,但是通过大量解析Rails服务器错误消息和数据库客户端,我能够按摩这个工作.这是我做的:

使用Rails 4,可以使用模型中的has_and_belongs_to_many关系创建关联,并在单独的迁移中使用create_join_table创建关联.当然,使用轨道发电​​机不符合我们的目标.另请注意,create_join_table的工作方式不同,甚至可能在以前版本的Rails中不可用.

第1步.为没有命名空间的连接表生成迁移.我们稍后会调整它.

$ rails g migration CreateModelAModelBJoinTable model_a model_b

# db/migrate/<somenumbers>_create_model_a_model_b_join_table.rb
class CreateModelAModelBJoinTable < ActiveRecord::Migration
  def change
    create_join_table :model_as, :model_bs do |t|
      # t.index [:model_a_id, :model_b_id]
      # t.index [:model_b_id, :model_a_id]
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

迁移需要一些按摩.我们需要:

  1. 覆盖表名以考虑名称空间
  2. (可选)选择索引.提示:如果名称空间和模型名称很长,则可能必须覆盖索引名称,如果它超出了数据库强加的字符限制.

这是最终的连接表迁移,注意在表名中包含命名空间,但在索引中排除了命名空间.简单地说,这将把表及其索引命名为rails has_and_belongs_to_many期望的方式.

# db/migrate/<somenumbers>_create_model_a_model_b_join_table.rb
class CreateModelAModelBJoinTable < ActiveRecord::Migration
  def change
    create_join_table :model_as, :model_bs, table_name: :namespace_model_as_namespace_model_bs do |t|
      t.index [:model_a_id, :model_b_id], name: :index_namespace_model_ab # or whatever, according to your database naming scheme
      # t.index [:model_b_id, :model_a_id]
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

第2步.使用has_and_belongs_to_many关联设置我们的模型.

除了关联之外,我们还需要覆盖类名和连接表名.

# app/models/namespace/model_a.rb
class Namespace::ModelA < ActiveRecord::Base
  has_and_belongs_to_many :namespace_model_b, class_name: "Namespace:ModelB", join_table: "namespace_model_as_namespace_model_bs"
end
Run Code Online (Sandbox Code Playgroud)

第3步.运行数据库迁移

rake db:migrate
Run Code Online (Sandbox Code Playgroud)

如果遇到问题,请提供最终提示

您可以随时退出迁移,删除它,然后重新开始:

$ rake db:rollback STEP=1
$ rails d migration CreateModelAModelBJoinTable
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!