
Routes | Ruby on Rails
Introduction to Routes in Ruby on Rails
Before delving into the main concepts of models in Ruby on Rails, let's take a closer look at what models are and why they are used.
Model in Ruby on Rails is the main component of the Model-View-Controller (MVC) design pattern used for web application development. The model represents an object that is responsible for storing and processing application data. The model provides access to the data and its persistence through the database connection.
The main purpose of models is to store and retrieve data from the database and provide secure access to it. Additionally, models handle the processing and validation of user input data before it is stored in the database.
Model Structure in Ruby on Rails includes all the necessary attributes and methods that define the model's behavior. Attributes represent the object's characteristics that can be stored in the database, such as name, surname, email, etc. Methods are used to perform operations on the model, such as creating, reading, updating, and deleting records. The model's structure involves defining a database table that corresponds to a specific model and establishing relationships between models. The naming convention is used to define the table in the database that corresponds to the model. The model name is written in
CamelCase , while the table name in the database is written in snake_case , using lowercase letters and separated by an underscore "_".
For example, if our application has a User model, the corresponding database table will be named "users". ActiveRecord automatically knows which database table corresponds to a specific model, so it does not need to be explicitly specified.
Relationship Between Models and the database in Ruby on Rails is facilitated by ActiveRecord. ActiveRecord is an Object-Relational Mapping (ORM) that maps application objects to database tables. This means that ActiveRecord allows working with the database using objects, simplifying the interaction with the database and ensuring cleaner and structured code.
In other words, ActiveRecord allows performing CRUD operations (Create, Read, Update, Delete) on the database using model objects. Instead of writing complex SQL queries, ActiveRecord methods can be used to interact with the database.
To define the relationship between two models, you need to determine the type of relationship used (one-to-one, one-to-many, many-to-many) and specify which model is the "parent" and which is the "child".
One-to-One Relationship - is a relationship between two database tables where each record in one table references one and only one record in the other table, and vice versa. This type of relationship can be used when you have tables that contain additional information about objects already stored in the database, for example, a users table and a user profiles table.
In Rails, the has_one method is used to define a one-to-one relationship. For example, if you have a users table and a user profiles table, the user model class can look like this:
class User < ApplicationRecord
has_one :profile
end
And the user profile model class can look like this:
class Profile < ApplicationRecord
belongs_to :user
end
In this example, the has_one sets up a one-to-one relationship between the users and user profiles tables, and the belongs_to specifies that the user profile model belongs to the user model.
Now that you have defined the model classes with the appropriate associations, you can easily retrieve a user's profile using the profile method:
user = User.find(1)
profile = user.profile
If you want to find the user associated with a profile, you can use the user method:
profile = Profile.find(1)
user = profile.user
In ActiveRecord, a "one-to-one" relationship is used when there is a relationship between two models that follows the "one-to-one" principle. This relationship can be configured using the belongs_to and has_one methods, which provide access to the associated records and perform operations with them. It's also worth noting that when creating a "one-to-one" relationship in ActiveRecord, an exchange key is automatically created between the two tables, allowing for quick access to the related data.
The "One-to-Many" relationship between two models occurs when one model has many records that refer to records in another model. The "One-to-Many" relationship is established using the has_many method in one model and the belongs_to method in another.
Let's consider an example with two models - User and Post. In our application, each user can have multiple posts, but each post can have only one author. Therefore, we will have a "One-to-Many" relationship between User and Post models.
# User Model
class User < ApplicationRecord
has_many :posts
end
# Post Model
class Post < ApplicationRecord
belongs_to :user
end
In this code, the has_many method establishes a relationship between User and Post . It specifies that the User model can have many posts and maintains the relationship between User and Post in the database.
The belongs_to method indicates that each post belongs to a user. It maintains the relationship between Post and User in the database.
Now that we have established a relationship between User and Post , we can easily retrieve all the posts belonging to a user or the user who wrote a specific post. For example, to get all the user's posts with an identifier of 1 , we can write:
user = User.find(1)
user_posts = user.posts
This will return an ActiveRecord::Relation object that contains all the posts belonging to a user with an identifier of 1 .
We can also easily get the author for a specific post using the belongs_to method. For example, to get the author for a post with an identifier of 1 , we can write:
post = Post.find(1)
post_author = post.user
A one-to-many relationship in a model is used when one model can be associated with multiple records in another model. For this, associations are used, specifically the has_many method in the parent model and the belongs_to method in the child model. This type of relationship is very common and is used in many real-world projects.
In Rails, to establish a many-to-many association between models, you can use two methods: has_and_belongs_to_many and has_many :through.
has_and_belongs_to_many is used when the association between models is simple and does not contain any additional information. For example, if we have the models User and Group, and each user can belong to multiple groups, and each group can contain multiple users, we can establish the association as follows:
class User < ApplicationRecord
has_and_belongs_to_many :groups
end
class Group < ApplicationRecord
has_and_belongs_to_many :users
end
Rails will automatically create a database table named groups_users that will contain the associations between users and groups.
If the association between models contains additional information, for example, if we have the models User, Product, and Order, and each user can order multiple products, each product can be ordered by multiple users, and each order can contain multiple products, then we can use has_many :through.
class User < ApplicationRecord
has_many :orders
has_many :products, through: :orders
end
class Product < ApplicationRecord
has_many :orders
has_many :users, through: :orders
end
class Order < ApplicationRecord
belongs_to :user
belongs_to :product
end
In this example, we use the Order model as an intermediary between users and products. Each association between User and Product goes through Order. To find all products ordered by a specific user, you can use the following code:
class User < ApplicationRecord
has_many :orders
has_many :products, through: :orders
end
class Product < ApplicationRecord
has_many :orders
has_many :users, through: :orders
end
class Order < ApplicationRecord
belongs_to :user
belongs_to :product
end
class User < ApplicationRecord
has_and_belongs_to_many :groups
end
In this example, we use the Order model as an intermediary between users and products. Each association between User and Product goes through Order. To find all products ordered by a specific user, you can use the following code:
user = User.find(1)
user.products
Using has_many :through allows us to establish a many-to-many relationship between two models through a third model, enabling the use of additional attributes and logic.
With has_many :through, we can perform various operations such as saving associated model attributes during record creation using the create method, or filtering records using the where method. We can also use has_many :through to perform different queries with related model objects.
On the other hand, has_and_belongs_to_many is a simpler way to establish a many-to-many relationship between two models without the need for a third model as a join table. However, using has_and_belongs_to_many limits the ability to add additional attributes and logic.
In Rails, polymorphic associations are relationships between tables where one table can belong to any of several tables.
For example, let's imagine a situation where we have three tables: comments, posts, and articles. Each comment can only be associated with one post, but one post can have many comments. We can use polymorphic associations to achieve this.
In this case, we can define a polymorphic association between the comments, posts, and articles tables, which allows us to associate each comment with the corresponding post and article. With polymorphic associations, we can create a single association that works for multiple tables.
To define a polymorphic association in the Comment model, we can use the belongs_to method, which allows us to specify that a comment can belong to any record in the posts or articles tables. For example:
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
end
class Post < ApplicationRecord
has_many :comments, as: :commentable
end
class Article < ApplicationRecord
has_many :comments, as: :commentable
end
In this case, we have defined that Comment can belong to any model that uses polymorphism. In the Post and Article models, we indicated that comments can belong to these models.
When accessing associated records, we can use the regular Rails syntax. For example, to get all comments associated with a Post with id 1, we can do the following:
post = Post.find(1)
comments = post.comments
This will return an ActiveRecord::Relation object that contains all comments for the post with id 1. This object is polymorphic because its behavior depends on the context of usage. The same applies to articles:
article = Article.find(1)
articles = article.comments
In particular, we can use this object to perform further queries on the comments. For example, we can filter the comments based on a certain condition using the where method:
comments = Post.find(1).comments.where(approved: true)
The where method will return an ActiveRecord::Relation object that contains only the comments for which the approved field's value is true.
Also, we can use the count method to get the total number of comments for a post:
comments_count = Post.find(1).comments.count
The count method will return an integer representing the total number of comments for the post with id 1.
In general, polymorphism allows us to create more versatile models that can be associated with objects of different types and have different relationships with them. This helps reduce code duplication and make the application more flexible and scalable.