Skip to content

Returns the most similar models based on associated models in common

License

Notifications You must be signed in to change notification settings

jpawlyn/similar_models

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Similar Models

Adds a similar_#{model_name.plural} instance and class method to an active record model, but can be set to any name using as: {method name}.

The instance method returns models that have associated models in common ordered by most in common first.

A practical example for this could be linking to related blog posts when rendering an individual blog post. Related blog posts could be related by author, tag or author and tag combined.

The class method returns models ordered by most associated models in common.

A practical example for this could be displaying a list of blog post authors who have written many posts and/or have written posts with other authors who themselves have written many posts.

If the commonality count is the same then a second order clause of created_at takes precedence if present.

The association(s) have to be many to many, so either habtm or has_many :through.

Installation

Add this line to your application's Gemfile:

gem 'similar_models'

And then run:

$ bundle

Usage

Post example

class Post < ApplicationRecord
  has_many :author_posts
  has_many :authors, through: :author_posts
  has_and_belongs_to_many :tags

  has_similar_models :authors
  has_similar_models :tags, as: :similar_posts_by_tag
  has_similar_models :authors, :tags, as: :similar_posts_by_author_and_tag
end

class Tag < ApplicationRecord
end

class Author < ApplicationRecord
  has_many :author_posts
end

class AuthorPosts < ApplicationRecord
  belongs_to :author
  belongs_to :post
end

To return posts with authors in common with the post model by most in common first:

post.similar_posts

To return posts ordered by most authors in common:

Post.similar_posts

The returned object is an ActiveRecord::Relation and so chaining of other query methods is possible:

post.similar_posts.where(created_at: 10.days.ago..).limit(5)

To return posts with tags in common with the post model by most in common first:

post.similar_posts_by_tag

To return posts ordered by most tags in common:

Post.similar_posts_by_tag

To return posts with the authors and tags in common with the post model by most in common first:

post.similar_posts_by_author_and_tag

To return posts ordered by most authors and tags in common:

Post.similar_posts_by_author_and_tag

The count of the associated models in common is accessible on each returned model:

post.similar_posts_commonality_count
post.similar_posts_by_tag_commonality_count
post.similar_posts_by_author_and_tag_commonality_count

Note multiple associations for the instance method do not work with sqlite.

Pagination is not supported on the instance method due to the use of group by.

In conjunction with acts-as-taggable-on

If you use mbleigh/acts-as-taggable-on and want to find related users say across multiple contexts:

user.similar_users.where(taggings: { context: %w(skills interests) })

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

About

Returns the most similar models based on associated models in common

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages