这是我想要实现的一个简化示例,我对Rails相对较新,并且正在努力解决模型之间的关系问题.
我有两个模型,User模型和Category模型.用户可以与许多类别相关联.对于许多用户,特定类别可以出现在类别列表中.如果删除了特定类别,则应将其反映在用户的类别列表中.
在这个例子中:
我的Categories表包含五个类别:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ID | Name | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 1 | Sports | | 2 | News | | 3 | Entertainment | | 4 | Technology | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我的Users表包含两个用户:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ID | Name | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 1 | UserA | | 2 | UserB | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
UserA可以选择体育和科技作为他的类别
UserB可以选择新闻,体育和娱乐
删除了体育类别,UserA和UserB类别列表都反映了删除
我玩弄了一个创建一个UserCategories表,其中包含类别和用户的ID.这样的工作,我可以查找类别名称,但我无法得到级联删除工作,整个解决方案似乎错了.
使用我发现的belongs_to和has_many函数的例子似乎讨论了映射一对一的关系.例如,对博客文章的评论.
cor*_*ard 140
你想要一段has_and_belongs_to_many感情.该指南很好地描述了它如何与图表和一切一起工作:
http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association
你最终会得到这样的东西:
# 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
Run Code Online (Sandbox Code Playgroud)
现在,您需要为Rails创建一个连接表以供使用.Rails不会自动为您执行此操作.这实际上是一个表,其中包含对每个类别和用户的引用,而没有主键.
从CLI生成迁移,如下所示:
bin/rails g migration CreateCategoriesUsersJoinTable
Run Code Online (Sandbox Code Playgroud)
然后将其打开并编辑以匹配:
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
有了这些,运行您的迁移,您可以使用您习惯的所有方便的访问者连接类别和用户:
User.categories #=> [<Category @name="Sports">, ...]
Category.users #=> [<User @name="UserA">, ...]
User.categories.empty?
Run Code Online (Sandbox Code Playgroud)
Dar*_*ich 11
最受欢迎的是“单传递关联”,你可以这样做:
class Book < ApplicationRecord
has_many :book_authors
has_many :authors, through: :book_authors
end
# in between
class BookAuthor < ApplicationRecord
belongs_to :book
belongs_to :author
end
class Author < ApplicationRecord
has_many :book_authors
has_many :books, through: :book_authors
end
Run Code Online (Sandbox Code Playgroud)
has_many :through 关联通常用于与另一个模型建立多对多连接。这种关联表明声明模型可以通过第三个模型与另一个模型的零个或多个实例相匹配。例如,考虑患者预约看医生的医疗实践。参考:https : //guides.rubyonrails.org/association_basics.html#the-has-many-through-association
只是补充上面 coreyward 的答案:如果您已经有一个具有belongs_to,has_many关系的模型,并且您想has_and_belongs_to_many使用同一个表创建一个新关系,您将需要:
rails g migration CreateJoinTableUsersCategories users categories
Run Code Online (Sandbox Code Playgroud)
然后,
rake db:migrate
Run Code Online (Sandbox Code Playgroud)
之后,您需要定义您的关系:
用户.rb:
class Region < ApplicationRecord
has_and_belongs_to_many :categories
end
Run Code Online (Sandbox Code Playgroud)
类别.rb
class Facility < ApplicationRecord
has_and_belongs_to_many :users
end
Run Code Online (Sandbox Code Playgroud)
为了使用旧数据填充新的联接表,您需要在控制台中执行以下操作:
User.all.find_each do |u|
Category.where(user_id: u.id).find_each do |c|
u.categories << c
end
end
Run Code Online (Sandbox Code Playgroud)
您可以保留类别和用户表中的user_id列和category_id列,也可以创建迁移以将其删除。
| 归档时间: |
|
| 查看次数: |
64279 次 |
| 最近记录: |