How to make a unique combination of data in the rails intermediate table

Introduction

Like Twitter, one user can like multiple tweets, and one tweet likes multiple users. I think we often implement many-to-many relationships such as! The combination must be unique because some users like only once per tweet. This time, I will explain how to make the combination of data in the intermediate table unique.

Development environment

Rails 6.0.3 Ruby 2.7.1 Tests: Rspec, FactoryBot, shoulda-matchers

1. Table

The following three tables are used this time.

User table

id name email
1 User 1 [email protected]
2 User 2 [email protected]

Tweet table

id content
1 tweet1
2 tweet2

Like table (intermediate table)

id user_id tweet_id
1 1 2
2 1 3

Many-to-many relationship

I will omit the many-to-many explanation this time.

user.rb


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

tweet.rb


class Tweet < ApplicationRecord
  has_many_to :likes
end

like.rb


class Like < ApplicationRecord
  belongs_to :user
  belongs_to :tweet
end

2. How to make a combination unique

And it is implemented in the main this time. There are two things to do.

  1. Add unique constraint to migration file with add_index (constrain DB)
  2. Add validation to the model of the intermediate table (add validation on the application side)

2.1 Add unique constraint to migration file with add_index

Add ʻadd_index: likes, [: user_id,: tweet_id], unique: true` to the migration file of the intermediate table. Don't forget to migrate after adding!

class CreateLikes < ActiveRecord::Migration[6.0]
  def change
    create_table :likes do |t|
      t.references :user, null: false, foreign_key: true
      t.references :tweet, null: false, foreign_key: true

      t.timestamps
    end
    add_index :likes, [:user_id, :tweet_id], unique: true   #Add here
  end
end

2.2 Add validation to model of intermediate table

Add validates: hotel_id, uniqueness: {scope:: staff_id} to the intermediate table model.

like.rb


class Like < ApplicationRecord
  belongs_to :user
  belongs_to :tweet

  validates :user_id, uniqueness: { scope: :tweet_id }  #Add here
end

That's all the required implementation. Make sure you can only register the same combination once in the console.

3. Rspec test to ensure uniqueness

For reference, we will also introduce the test. It is assumed that Rspec, FactoryBot, and shoulda-matchers have been set.

like_spec.rb


require 'rails_helper'

RSpec.describe Like, type: :model do
  let(:user) { create(:user) }
  let(:tweet) { create(:tweet) }
  before { create(:like, user: user, tweet: tweet) }

  it { should belong_to(:user) }  #Check the many-to-many relationship between this line and the line below
  it { should belong_to(:tweet) }
  it { is_expected.to validate_uniqueness_of(:user_id).scoped_to(:tweet_id) } #Make sure it is unique here
end

in conclusion

Did you make the combination unique? I think that implementations like this one are often used, so I hope you find it helpful.

Recommended Posts

How to make a unique combination of data in the rails intermediate table
How to make a follow function in Rails
How to clear all data in a particular table
[Rails] How to change the column name of the table
How to store Rakuten API data in a table
[Ruby On Rails] How to search and save the data of the parent table from the child table
How to delete large amounts of data in Rails and concerns
How to change the maximum and maximum number of POST data in Spark
How to change the value of a variable at a breakpoint in intelliJ
How to get the absolute path of a directory running in Java
[Rails] How to create a table, add a column, and change the column type
How to make the schema of the URL generated by Rails URL helper https
[Order method] Set the order of data in Rails
Make a margin to the left of the TextField
How to implement a like feature in Rails
How to easily create a pull-down in Rails
How to use JQuery in js.erb of Rails6
(Ruby on Rails6) Creating data in a table
How to check Rails commands in the terminal
[Ruby on Rails] How to make the link destination part of the specified id
How to get the ID of a user authenticated with Firebase in Swift
[Rails] How to get rid of flash messages in a certain amount of time
How to store data simultaneously in a model associated with a nested form (Rails 6.0.0)
How to set the display time to Japan time in Rails
How to implement a like feature in Ajax in Rails
How to create a data URI (base64) in Java
[Ruby / Rails] Set a unique (unique) value in the class
[How to insert a video in haml with Rails]
[Rails 6] How to set a background image in Rails [CSS]
[Rails] How to get the contents of strong parameters
How to make a mod for Slay the Spire
[Rails] How to load JavaScript in a specific view
[Rails] How to display an image in the view
How to install Docker in the local environment of an existing Rails application [Rails 6 / MySQL 8]
[Rails] How to delete production environment MySQL data after putting it in the development environment
[Rails] I want to display the link destination of link_to in a separate tab
[Rails] How to make seed
[Rails] How to display the weather forecast of the registered address in Japanese using OpenWeatherMap
[Rails] Processing after adding a column to the devise table
How to create a placeholder part to use in the IN clause
How to display a graph in Ruby on Rails (LazyHighChart)
[Ruby] How to retrieve the contents of a double hash
A validation error occurred when saving to the intermediate table.
Let's summarize how to extend the expiration date of Rails
How to add the same Indexes in a nested array
How to derive the last day of the month in Java
I tried to make a client of RESAS-API in Java
[Rails] Where to be careful in the description of validation
[jsoup] How to get the full amount of a document
[Rails] How to display information stored in the database in view
[Rails Tutorial Chapter 2] What to do when you make a mistake in the column name
How to add columns to a table
[Rails] How to write in Japanese
How to make a Java container
How to make a JDBC driver
How to make a Jenkins plugin
How to make a Maven project
How to make a Java array
How to install Swiper in Rails
[Rails / Routing] How to refer to the controller in the directory you created
[Rails] How to get the URL of the transition source and redirect