Modular Models in Ruby on Rails

sulmanweb

Sulman Baig

Posted on May 30, 2022

Modular Models in Ruby on Rails

Every so often we want our models not just in model folder but in module in a folder with many advantages inclusive.
One advantage is maybe those table names are already in project, so by putting a prefix of module name can make the table uniqueness.
Next advantage is you want to put the functionality separate with the rest of the project, we can use modular models.
Last advantage is making engines to be used in other projects, including tables, can be easy using prefixed tables.

How to do it? It’s easy!

Let’s assume we want a blog to our project, which is a separate functionality than the rest of the project. So, we will be creating two models, Post and Comment.

Therefore, run in the project:

rails g model blog/post title:string body:text 
Enter fullscreen mode Exit fullscreen mode

This will create a model with the following files:
blog.rb

# app/models/blog.rb

module Blog
  def self.table_name_prefix
    'blog_'
  end
end
Enter fullscreen mode Exit fullscreen mode

blog/post.rb

# app/models/blog/post.rb

module Blog
  class Post < ApplicationRecord
    validates :title, presence: true
    validates :body, presence: true
  end
end
Enter fullscreen mode Exit fullscreen mode

And the migration file will create the table named blog_posts not just simple posts.

Now, creating the comments in the post is somewhat tricky.
Run the following in the terminal:

rails g model blog/comment body:text blog_post:references user:references
Enter fullscreen mode Exit fullscreen mode

This will ask to override the blog.rb which is not needed at the moment.
The new file of comment model needs to be updated:

# app/models/blog/comment.rb

module Blog
  class Comment < ApplicationRecord
    validates :body, presence: true
    belongs_to :blog_post, class_name: 'Blog::Post'
  end
end
Enter fullscreen mode Exit fullscreen mode

And update the post model with relation:

# app/models/blog/post.rb

has_many :comments, class_name: 'Blog::Comment', dependent: :destroy, foreign_key: :blog_post_id, inverse_of: :blog_post
Enter fullscreen mode Exit fullscreen mode

Final ponts

So now we have modular models in the project. Tables created will be blog_posts and blog_comments. Anywhere in project to call post model you have to use Blog::Post like Blog::Post.find 12. But we can use .comments like:

# rails console
post = Blog::Post.find 1
post.comments.last
# similar for comments
comment = Blog::Comment.last
comment.post.title
Enter fullscreen mode Exit fullscreen mode

However, in database we will have blog_posts table and blog_comments table with foreign key blog_post_id.


Happy Coding!

💖 💪 🙅 🚩
sulmanweb
Sulman Baig

Posted on May 30, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related