为什么我不能在两个表中使用t 1:m关联来形成m:m关联?

时间:2010-12-10 10:35:42

标签: ruby-on-rails

我是铁杆新手,我今天下午想到了这个想法

这是我的代码:

视频表迁移文件:

class CreateVideos < ActiveRecord::Migration
  def self.up
    create_table :videos do |t|
      t.string :title
      t.string :drummer_id

      t.timestamps
    end
  end

  def self.down
    drop_table :videos
  end
end

鼓手表迁移文件:

class CreateDrummers < ActiveRecord::Migration
  def self.up
    create_table :drummers do |t|
      t.string :first_name
      t.string :video_id
      t.timestamps
    end
  end

def self.down     drop_table:鼓手   结束 端

drummer.rb

class Drummer < ActiveRecord::Base
 belongs_to :video
 has_many :videos 
end

video.rb

class Video&lt;的ActiveRecord :: Base的   has_many:鼓手   belongs_to:鼓手 端

据我所知

Drummer.create(:first_name => "Jojo")

Drummer.find_by_first_name("Jojo").videos.create(:title => "JojoVideo1")

没关系

但 在另一边,什么都没有!

Video.find_by_title("JojoVideo1").drummers
=>[]

我检查所有匹配的外键,但我不知道上面的查询返回一个空白数组。

2 个答案:

答案 0 :(得分:1)

我不知道你的代码有什么问题。但我想建议另一种方式。您可以创建一个连接模型,它将为您处理多对多关联。使用连接模型可以更好地控制代码。这可以通过以下方式完成:

class A < ActiveRecord::Base
has_many :cs
has_many :bs, :through => cs
end

class B < ActiveRecord::Base
has_many :cs
has_many :as, :through => cs
end

class C < ActiveRecord::Base
belongs_to :as
belongs_to :bs
end

以及每个模型的迁移如下

class CreateAs < ActiveRecord::Migration
  def self.up
    create_table :as do |t|
      t.string :title
      t.timestamps
    end
  end

  def self.down
    drop_table :as
  end
end


class CreateBs < ActiveRecord::Migration
  def self.up
    create_table :bs do |t|
      t.string :title
      t.timestamps
    end
  end

  def self.down
    drop_table :bs
  end
end


class CreateCs < ActiveRecord::Migration
  def self.up
    create_table :cs do |t|
      t.references :as
      t.references :bs
      t.timestamps
    end
  end

  def self.down
    drop_table :cs
  end
end

另一种方法是只创建一个没有模型的连接表。这可以通过以下方式完成: -

A类&lt;的ActiveRecord :: Base的 has_and_belongs_to_many:bs 端

B级&lt;的ActiveRecord :: Base的 has_and_belongs_to_many:as 端

希望你有更好的主意。

答案 1 :(得分:1)

 > Drummer.all
 => [#<Drummer id: 1, first_name: "Jojo", video_id: nil, created_at: "2010-12-10 11:04:48", updated_at: "2010-12-10 11:04:48">] 
 > Video.all
 => [#<Video id: 1, title: "JojoVideo1", drummer_id: "1", created_at: "2010-12-10 11:04:48", updated_at: "2010-12-10 11:04:48">] 
 > Video.all.first.drummer
 => #<Drummer id: 1, first_name: "Jojo", video_id: nil, created_at: "2010-12-10 11:04:48", updated_at: "2010-12-10 11:04:48"> 
 > Video.all.first.drummers
 => [] 

来自test / development.log:

  Video Load (0.3ms)  SELECT "videos".* FROM "videos"
  Drummer Load (0.3ms)  SELECT "drummers".* FROM "drummers" WHERE ("drummers"."id" = 1) LIMIT 1
  Video Load (0.3ms)  SELECT "videos".* FROM "videos"
  Drummer Load (0.3ms)  SELECT "drummers".* FROM "drummers" WHERE ("drummers".video_id = 1)

Video.all.first.drummer可以工作,因为可以通过视频然后检查他们的鼓手ID来找到它。另一个不起作用,因为它试图找到一个带有video_id的鼓手,而我们制作视频的方式没有设置鼓手的video_id。

我们可以用相反的问题构建视频/鼓手对:

d = Drummer.first
d.create_video(:title => "JojoVideo2")
d.save

这个新视频对鼓手来说效果不错,但对于鼓手来说效果不佳 - 因为这次鼓手有一个video_id,但视频没有鼓手_id。

实际的结果是你应该做Rohit所说的:)