在 Rails 中创建多对多关系 [英] Creating a many to many relationship in Rails

查看:41
本文介绍了在 Rails 中创建多对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我想要实现的目标的简化示例,我对 Rails 比较陌生,正在努力了解模型之间的关系.

我有两个模型,User 模型和 Category 模型.一个用户可以与许多类别相关联.特定类别可以出现在许多用户的类别列表中.如果某个特定类别被删除,这应该反映在用户的类别列表中.

在这个例子中:

我的 Categories 表包含五个类别:

<前>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|身份证 |姓名 |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|1 |体育 ||2 |新闻 ||3 |娱乐 ||4 |技术 |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我的 Users 表包含两个用户:

<前>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|身份证 |姓名 |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|1 |用户A ||2 |用户B |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<块引用>

UserA 可以选择 Sports 和 Technology 作为他的类别

用户 B 可以选择新闻、体育和娱乐

运动类别被删除,UserA和UserB类别列表都反映了删除

我曾尝试创建一个 UserCategories 表,该表包含类别和用户的 ID.这种工作,我可以查找类别名称,但我无法让级联删除工作,整个解决方案似乎是错误的.

我发现的使用belongs_to 和has_many 函数的示例似乎在讨论映射一对一关系.例如,对博客文章的评论.

  • 您如何使用内置的 Rails 功能来表示这种多对多关系?
  • 在使用 Rails 时,在两者之间使用单独的表是一种可行的解决方案吗?

解决方案

您需要 has_and_belongs_to_many 关系.该指南很好地描述了如何处理图表和所有内容:

http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

你会得到这样的结果:

# app/models/category.rb类别类别

现在您需要创建一个供 Rails 使用的连接表.Rails 不会自动为您执行此操作.这实际上是一个表,其中包含对每个类别和用户的引用,并且没有主键.

像这样从 CLI 生成迁移:

bin/rails g 迁移 CreateCategoriesUsersJoinTable

然后打开它并编辑它以匹配:

对于 Rails 4.0.2+(包括 Rails 5.2):

def 更改# 这就够了;您无需担心订单create_join_table :categories, :users# 如果要添加索引以通过此连接进行更快的查询:create_join_table :categories, :users do |t|t.index :category_idt.index :user_id结尾结尾

Rails <4.0.2:

def self.up# 按字母顺序排列的模型名称(例如 a_b)create_table :categories_users, :id =>假做 |t|t.integer :category_idt.integer :user_id结尾add_index :categories_users, [:category_id, :user_id]结尾def self.downdrop_table :categories_users结尾

有了它,运行您的迁移,您就可以将类别和用户与您习惯的所有便捷访问器连接起来:

User.categories #=>[<类别@name="体育">, ...]Category.users #=>[<User @name="UserA">, ...]用户.categories.empty?

This is a simplified example of what I am trying to achieve, I'm relatively new to Rails and am struggling to get my head around relationships between models.

I have two models, the User model and the Category model. A user can be associated with many categories. A particular category can appear in the category list for many users. If a particular category is deleted, this should be reflected in the category list for a user.

In this example:

My Categories table contains five categories:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| ID | Name                       |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 1  | Sports                     | 
| 2  | News                       |
| 3  | Entertainment              |
| 4  | Technology                 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

My Users table contains two users:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| ID | Name                       |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 1  | UserA                      | 
| 2  | UserB                      |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

UserA may choose Sports and Technology as his categories

UserB may choose News, Sports and Entertainment

The sports category is deleted, both UserA and UserB category lists reflect the deletion

I've toyed around with creating a UserCategories table which holds the ids of both a category and user. This kind of worked, I could look up the category names but I couldn't get a cascading delete to work and the whole solution just seemed wrong.

The examples of using the belongs_to and has_many functions that I have found seem to discuss mapping a one-to-one relationship. For example, comments on a blog post.

  • How do you represent this many-to-many relationship using the built-in Rails functionality?
  • Is using a separate table between the two a viable solution when using Rails?

解决方案

You want a has_and_belongs_to_many relationship. The guide does a great job of describing how this works with charts and everything:

http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

You will end up with something like this:

# app/models/category.rb
class Category < ActiveRecord::Base
  has_and_belongs_to_many :users
end

# app/models/user.rb
class User < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

Now you need to create a join table for Rails to use. Rails will not do this automatically for you. This is effectively a table with a reference to each of Categories and Users, and no primary key.

Generate a migration from the CLI like this:

bin/rails g migration CreateCategoriesUsersJoinTable

Then open it up and edit it to match:

For Rails 4.0.2+ (including Rails 5.2):

def change
  # This is enough; you don't need to worry about order
  create_join_table :categories, :users

  # If you want to add an index for faster querying through this join:
  create_join_table :categories, :users do |t|
    t.index :category_id
    t.index :user_id
  end
end

Rails < 4.0.2:

def self.up
  # Model names in alphabetical order (e.g. a_b)
  create_table :categories_users, :id => false do |t|
    t.integer :category_id
    t.integer :user_id
  end

  add_index :categories_users, [:category_id, :user_id]
end

def self.down
  drop_table :categories_users
end

With that in place, run your migrations and you can connect Categories and Users with all of the convenient accessors you're used to:

User.categories  #=> [<Category @name="Sports">, ...]
Category.users   #=> [<User @name="UserA">, ...]
User.categories.empty?

这篇关于在 Rails 中创建多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆