Tagliani

Blazing fast Ruby alternative to acts-as-taggable-on and other similar gems. Instead of million of records in the database it uses powerful ElasticSearch, which gives a very fast and scalable solution with a search capabilities of ElasticSearch.

Installation

All you need is to add in your Gemfile the follwing line.

gem 'tagliani'

And run bundle install command.

Requirements

  • ActiveRecord
  • redis-client
  • elasticsearch

To run this gem it is required to have ActiveRecord.

Configuration

In your rails app config/initializers create tagliani.rb with the following content

Tagliani.configure do |config|
  config.elasticsearch.url = "http://localhost:9200" # URL of your ElasticSearch service, by default set to this endpoint
  config.elasticsearch.index = "tagliani_#{Rails.env}" # Index name
  config.elasticsearch.refresh = true # false by default
  config.elasticsearch.log = true # false by default
  config.redis.url = "redis://localhost:6379/tagliani" # By default set to this endpoint
  config.redis.queue = "tagliani" # By default set to this queue name
  config.redis.length = 200 # By default set to 200. It is a queue length per bulk that is going to be sent to ElasticSearch
end

Let's say inside the Rails application you have a model with a name "Hashtag", that represents all the tags attached to the model "Tweet".

class Hashtag < ActiveRecord::Base
  include Tagliani::Concerns::Search
end

class Tweet < ActiveRecord::Base
  taggable tag_kls: "Hashtag"
end

tag_kls is optional. By default it set to Tag model

To attach the tag simply execute:

tweet = Tweet.create(body: "Follow @rrubyist on Twitter")
tweet.tags.add(name: '#followme')

To list the attached tags you can run:

tweet.tags

It will return you an array of Hashtag objects attached to the Tweet model.

[#<Hashtag id: 2, name: "#followme", sticker: "default">]

If you want to search for all tweets attached to the Hashtag model with a name #followme you can use public search method defined in class.

You don't have to specify tag_kls, unless you have multiple models that act as Tag model

Hashtag.search(where: { tag_name: ['#followme'], tag_kls: ['Hashtag'] }

Tag name represents the name field of the Hashtag model.

[#<Tweet id: 3, body: "Tweet #0">, #<Tweet id: 4, body: "Tweet #1">, 
#<Tweet id: 5, body: "Tweet #2">, #<Tweet id: 6, body: "Follow @rrubyist on Twitter">]

Asyncronous bulk index

For a non-blocking processes you can enable option to index jobs in background queue.

class Artist < ActiveRecord::Base
  has_many :albums
  tagliani async: true
end

To index in bulks, simply execute:

Tagliani::Search::Index.bulk!

Inherit tags from models

You can specify the models you want to inherit tags from by adding an option :inherit with a list of models in the taggable method.

class Album < ActiveRecord::Base
  has_many :songs
  belongs_to :artist
  belongs_to :producer

  taggable inherit: %i[artist producer]
end

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/rudkovskyi/tagliani. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Tagliani project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.