文档章节

Everything There Is to Know About Associations in Rails

Kolosek
 Kolosek
发布于 2018/05/10 17:29
字数 1117
阅读 5
Rails">收藏 0

An association is a connection between two Active Record models. It makes much easier to perform various operations on the records in your code. We will divide associations into four categories:

  1. One to One
  2. One to Many
  3. Many to Many
  4. Polymorphic One to Many

If you are new to Ruby on Rails, be sure to get up your rails project ready and check how to create models in Rails.

One to One

When you set up one-to-one relations you are saying that a record contains exactly one instance of another model. For example, if each user in your application has only one profile, you can describe your models as:

class User < ApplicationRecord       class Profile < ApplicationRecord
  has_one :profile                     belongs_to :user
end                                  end

One of the models in the given relation will have has_one method invocation and another one will have belongs_to. It is used to describe which model contains a foreign key reference to the other one, in our case, it is the profiles model.

one-to-one

Cover your associations with RSpec tests to make sure everything works the way you want it to.

One to Many

one-to-many association is the most common used relation. This association indicates that each instance of the model A can have zero or more instances of another model B and model B belongs to only one model A.

Let's check it out via example. We want to create an application where users can write multiple stories, our models should look like this:

class User < ApplicationRecord       class Story < ApplicationRecord
  has_many :stories                     belongs_to :user
end                                  end

Here, deciding which model will have has_many and which will have belongs_to is more important than in one-to-one relations, because it changes the logic of your application. In both cases, the second model contains one reference to the first model in form of a foreign key.

The second model doesn't know about the first model relation to it - it is not aware if the first model has a reference to more than one of them or just to one.

one-to-many
The tests for associations get more complex to write the more relations you create. You should check it out how to create your own association factories to make your testing life easier.

Many to Many

Many-to-many associations are a bit more complex and can be handled in two ways, "has and belongs to many" and "has many through" relations.

Has and Belongs to Many

has_and_belongs_to_many association creates a direct many-to-many connection with another model. It is simpler than the other one, as it only requires calling has_and_belongs_to_many from both models.

has-and-belongs-to-many

Example: Let's say, a user can have many different roles and the same role may contain many users, our models would be like this:

class User < ApplicationRecord       class Role < ApplicationRecord
  has_and_belongs_to_many :roles       has_and_belongs_to_many :users
end                                  end

You will need to create a join table for this association to work. It is a table that connects two different models. The join table is created with rails function create_join_table :user, :role in a separate migration.

class CreateUserRoles < ActiveRecord::Migration
  def change
    create_table :user_roles, id: false do |t|
      t.references :user, index: true, foreign_key: true
      t.references :role, index: true, foreign_key: true
    end
  end
end

This is a very simple approach, but you don't have the direct access to related objects, you can only hold references to two models and nothing else.

Has Many Through

Another way to define a many-to-many association is to use the has many through association type. Here we define a separate model, to handle that connection between two different ones.

has_many_through

Instead of putting down a new example, you should check this one out! It explains everything you should know about this association.

Using the example of has_and_belongs_to_many association, this time the three models should be written like this:

class User < ApplicationRecord
  has_many :user_roles
  has_many :roles, through: :user_roles
end
 
class UserRoles < ApplicationRecord
  belongs_to :user
  belongs_to :role
end
 
class Role < ApplicationRecord
  has_many :user_roles
  has_many :users, through: :user_roles
end

This association will enable you to do things like user.role and to get a list of all connected second model instances. It will also enable you to get access to data specific to the relation between first and second models.

Polymorphic

Polymorphic associations are the most advanced associations available to us. You can use it when you have a model that may belong to many different models on a single association.

polymorphic

Let's imagine you want to be able to write comments for users and stories. You want both models to be commentable. Here's how this could be declared:

class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end
 
class Employee < ApplicationRecord
  has_many :comment, as: :commentable
end
 
class Product < ApplicationRecord
  has_many :comment, as: :commentable
end

You can think of a polymorphic belongs_to declaration as setting up an interface that any other model can use. To declare the polymorphic interface you need to declare both a foreign key column and a type column in the model. You should run the migration once you are done.

class CreateComments < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.text :body
      t.integer :commentable_id
      t.string :commentable_type
      t.timestamps
    end
 
    add_index :comments, :commentable_id
  end
end

This migration can be simplified by using references:

class CreateComments < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.text :body
      t.references :commentable, polymorphic: true, index: true
      t.timestamps
    end
  end
end

Aditional Options

There are a few additional options you can use when defining relations between models, we will cover two most commonly used ones.

class_name

If the name of the other model cannot be derived from the association name, you can use the :class_name option to supply the model name. You can read more about this on RailsGuides.

Example: You want the belongs_to relation to call for an author, but there are two problems:

  1. There is no model called in that way.
  2. The story table is missing an author_id field.

Easy fix! To make this work and stop your tests from failing, you just have to specify the :foreign_key and the actual name of the class:

class Story < ApplicationRecord
  belongs_to :author, class_name: 'User', foreign_key: 'user_id'
end

dependent

You can use this option when you want to get rid of orphaned records since they can lead to various problems. Orphaned records are created when we delete or destroy a model A that was associated with model B, but model B wasn't removed in the process.

class User < ApplicationRecord
  has_many :stories, dependent: :destroy
end

Example: Suppose, a user called Maria wrote a lot of stories. Then, we deleted Maria from the database, but the stories still have the user_id column set to Maria's id. These stories are called orphaned records.

Thank you for reading!

This article is originally published on Kolosek Blog.

© 著作权归作者所有

Kolosek
粉丝 0
博文 29
码字总数 20461
作品 0
塞尔维亚
CEO
私信 提问
rails ActiveRecord 中的保留关键字

Automatically gets set to the current date and time when the record is first created. - Automatically gets set to the current date and time whenever the record is updated. - Add......

YuDong7
2017/10/19
13
0
Rails 3.2.3 RC1 发布

Rails 3.2.3 RC1 发布了,该版本修改了 config.active_record.whitelist_attributes 的默认值为 true,该版本会影响到新生成的应用程序,那些使用升级的用户不存在向后兼容性问题,更详细的信...

红薯
2012/03/29
515
0
安全问题一,关于表单映射model属性传递(mass assignment)方面的疑虑?

引子: 今天(现在零点,实际应该是昨天了)中午看一点ruby on rails方面的东西,准确说,ruby只是刚安装了敲了个puts、def,on rails则看没见到影子了。 说重点,巧了看到mass assignment问题...

bs2004
2012/03/31
1K
3
JRuby gem for GlassFish V3 server

GlashFish V3 前两天刚除了预发行版本,今天 JRuby 推出了为其定制的版本。 安装方法 ============ gem install glassfish 新的特性 ============ * Based on GlassFish v3 Prelude nucleus...

红薯
2008/11/08
421
0
ROS 下 orbslam2 RGB-D (四)

一 . 利用数据集测试 # 6. RGB-D Example ## TUM Dataset 1. Download a sequence from http://vision.in.tum.de/data/datasets/rgbd-dataset/download and uncompress it. 2. Associate RG......

v7xyy
2017/10/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

面试官,Java8 JVM内存结构变了,永久代到元空间

在文章《JVM之内存结构详解》中我们描述了Java7以前的JVM内存结构,但在Java8和以后版本中JVM的内存结构慢慢发生了变化。作为面试官如果你还不知道,那么面试过程中是不是有些露怯?作为面试...

程序新视界
7分钟前
7
0
读书笔记:深入理解ES6 (八)

第八章 迭代器(Iterator)与生成器(Generator) 第1节 循环语句的问题   在循环、多重循环中,通过变量来跟踪数组索引的行为容易导致程序出错。迭代器的出现旨在消除这种复杂性,并减少循...

张森ZS
7分钟前
4
0
Elasticsearch 实战(一) - 简介

官腔 Elasticsearch,分布式,高性能,高可用,可伸缩的搜索和分析系统 基本等于没说,咱们慢慢看 1 概述 百度:我们比如说想找寻任何的信息的时候,就会上百度去搜索一下,比如说找一部自己喜...

JavaEdge
12分钟前
3
0
【jQuery基础学习】11 jQuery性能简单优化

本文转载于:专业的前端网站➦【jQuery基础学习】11 jQuery性能简单优化 关于性能优化 合适的选择器 $("#id")会直接调用底层方法,所以这是最快的。如果这样不能直接找到,也可以用find方法继...

前端老手
20分钟前
5
0
重磅发布 | 全球首个云原生应用标准定义与架构模型 OAM 正式开源

导读:2019 年 10 月 17 日,阿里巴巴合伙人、阿里云智能基础产品事业部总经理蒋江伟(花名:小邪)在 Qcon 上海重磅宣布,阿里云与微软联合推出开放应用模型 Open Application Model (OAM...

阿里云官方博客
23分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部