Table of Contents generated with DocToc
- EasyTags
- Migrating from ActsAsTaggableOn
- Installation
- Post Installation
- Usage
- Setup
- Interface
- Examples
- Adding/Removing tags
- Querying
- Context relations
- Global relations
- Callbacks
- Instance scope callbacks
- Active Support Instrumentation custom notifications
- Tag notifications
- Tagging notifications
- Dirty objects
- Configuration
- Testing
- Development
- Contributing
- License
EasyTags
Easy contextual tagging for Rails
Migrating from ActsAsTaggableOn
This gem was inspired by ActsAsTaggableOn. It was built on similar model, but rewritten from scratch and simplified with better maintainability in mind. Considerable amount of features has been removed and we've made some breaking changes. Please refer to ActsAsTaggableOn migration notes if you want to migrate
Installation
Add this line to your application's Gemfile:
gem 'easy_tags'And then execute:
$ bundlePost Installation
generate migration with:
rails g easy_tags:migrationUsage
Setup
in your ActiveRecord model add:
include EasyTags::Taggable
easy_tags_on :highlightswith multiple tag contexts:
include EasyTags::Taggable
easy_tags_on :highlights, :tags, :notesInterface
upon the easy_tags_on declaration:
easy_tags_on :highlightsthe following methods will be auto-generated and made available for your model instance (highlights being an example context name):
| description | method |
|---|---|
| set tags using string of tag names | highlights_list=(value) |
| get string of tag names | highlights_list |
| get string of persisted tag names | highlights_list_persisted |
| set tags with array of tag names | highlights=(value) |
| get array of tag names | highlights |
- the String accessor is helpful when working with client side tagging UI solutions such as ie. select2
- the Array accessor gives you convenient array item manipulation
Examples
Adding/Removing tags
Using Array accessor
# assign/replace tags (comma separated using the default parser)
model.highlights = ['My Tag', 'Second Tag', 'Some Other tag']
# => [
# [0] "My Tag",
# [1] "Second Tag",
# [2] "Some Other tag"
# ]
# add tags
model.highlights.add('One More', 'And Another')
model.highlights
# => [
# [0] "My Tag",
# [1] "Second Tag",
# [2] "Some Other tag",
# [3] "One More",
# [4] "And Another"
# ]
# remove a single tag
model.highlights.remove('One More')
model.highlights
# => [
# [0] "My Tag",
# [1] "Second Tag",
# [2] "Some Other tag",
# [3] "And Another"
# ]
# remember to persist changes
model.saveUsing String accessor
# add multiple tags (comma separated using the default parser)
model.highlights_list = 'My Tag, Second Tag, Some Other tag'
# > "My Tag, Second Tag, Some Other tag"
# remove a single tag
model.highlights_list = 'My Tag, Second Tag'
# > "My Tag, Second Tag"
# remove all tags
model.highlights_list = ''
# remember to persist changes
model.saveQuerying
EasyTags does not offer any query helper scopes, but it's fairly easy to query without them.
Context relations
Upon the easy_tags_on declaration:
easy_tags_on :highlightsthe following relations will be auto-generated and made available for your model instance (highlights being an example context name):
| description | relation |
|---|---|
has_many to EasyTags::Tag relation |
highlights_tags |
has_many to EasyTags::Taggings relation |
highlights_taggings |
-
EasyTags::Tagmodel represents a single tag name -
EasyTags::Taggingsrepresents a join table between your model and theEasyTags::Tagmodel, it also holds the tag context value
Find all model instances with a specific tag name:
MyModel.joins(:highlights_tags).where(tags: { name: 'My Tag' })Eager loading:
MyModel.includes(:highlights_tags)Global relations
Upon the EasyTags::Taggable inclusion
include EasyTags::Taggablethe fallowing context independent relations will be auto-generated and made available for your model instance:
| description | relation |
|---|---|
has_many to EasyTags::Taggings relation |
has_many :taggings, as: :taggable |
has_many to EasyTags::Tag relation |
has_many :base_tags, through: :taggings |
You can use them for querying multiple contexts
MyModel.joins(:base_tags).where(taggings: { context: %w[highlights billing_highlights] })Callbacks
Instance scope callbacks
include EasyTags::Taggable
easy_tags_on(
highlights: { after_add: :add_tag_callback, after_remove: -> (tagging) { puts "removed #{tagging.tag.name}" } }
)
def add_tag_callback(tagging)
puts "added #{tagging.tag.name}"
endActive Support Instrumentation custom notifications
Tag notifications
ActiveSupport::Notifications.subscribe 'easy_tag.tag_added' do |tag|
puts "added #{tag.name}"
endActiveSupport::Notifications.subscribe 'easy_tag.tag_removed' do |tag|
puts "removed #{tag.name}"
endTagging notifications
ActiveSupport::Notifications.subscribe 'easy_tag.tagging_added.YOUR_MODEL_TABLEIZED.CONTEXT_NAME' do |tagging|
puts "added #{tagging.tag.name}"
endActiveSupport::Notifications.subscribe 'easy_tag.tagging_added.YOUR_MODEL_TABLEIZED.CONTEXT_NAME' do |tagging|
puts "removed #{tagging.tag.name}"
endDirty objects
EasyTags implements ActiveModel::Dirty attribute changes tracking fot all the context String accessors (the CONTEXT_NAME_list attributes)
model.highlights
# []
model.highlights = ['Tag One', 'Tag Two']
# [
# [0] "Tag One",
# [1] "Tag Two"
# ]
model.changed?
# true
model.highlights_list_changed?
# true
model.highlights_list_was
# ""
model.highlights_list_change
# [
# [0] "",
# [1] "Tag One,Tag Two"
# ]
model.save
# true
model.changed?
# false
model.highlights_list_changed?
# false
model.previous_changes
# {
# "highlights_list" => [
# [0] nil,
# [1] "Tag One,Tag Two"
# ]
# }
model.highlights_list_previously_changed?
# true
model.highlights_list_previous_change
# [
# [0] nil,
# [1] "Tag One,Tag Two"
# ]Configuration
# config/initializers/easy_tags.rb
EasyTags.setup do |config|
config.tags_table = :tags
config.taggings_table = :taggings
config.parser = EasyTags::Parsers::Default
config.generator = EasyTags::Generators::Default
endYou can customize db table names with tags_table and taggings_table options.
You can customize the parser and the generator to use different separators, filtering or processing. The default parser uses comma as separator and is case sensitive.
Testing
bundle exec appraisal install
bundle exec appraisal rspec
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/easy_tags. 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.