NoFlyList: Custom Tag Screening with NoFlyList

Tag parsing seems simple until you handle real user input.
Let’s explore how NoFlyList’s transformers handle messy tag data submitted.
Basic Setup
rails generate no_fly_list:transformer
Default transformer:
module ApplicationTagTransformer
module_function
def parse_tags(tags)
if tags.is_a?(Array)
tags
else
tags.split(separator).map(&:strip).compact
end
end
def recreate_string(tags)
tags.join(separator)
end
def separator
','
end
end
Real-World Examples
Hashtag Transformer
module HashtagTransformer
module_function
def parse_tags(tags)
return tags if tags.is_a?(Array)
tags.scan(/#[\w-]+/).map { |tag| tag.delete('#') }
end
def recreate_string(tags)
tags.map { |tag| "##{tag}" }.join(' ')
end
end
class Post < ApplicationRecord
include NoFlyList::TaggableRecord
has_tags :hashtags, transformer: HashtagTransformer
end
post = Post.new(content: "Check out #rails #ruby #webdev")
post.hashtags_list = post.content # Extracts: ["rails", "ruby", "webdev"]
Multi-Language Transformer
module MultiLangTransformer
module_function
def parse_tags(tags)
return tags if tags.is_a?(Array)
tags.split('|').map do |tag_pair|
lang, tag = tag_pair.split(':').map(&:strip)
"#{lang}:#{tag}"
end
end
def recreate_string(tags)
tags.join(' | ')
end
end
class Article < ApplicationRecord
has_tags :keywords, transformer: MultiLangTransformer
end
article.keywords_list = "en:ruby | es:rubí | fr:rubis"
Hierarchical Tag Transformer
module CategoryTransformer
module_function
def parse_tags(tags)
return tags if tags.is_a?(Array)
tags.split('>').map(&:strip)
end
def recreate_string(tags)
tags.join(' > ')
end
end
class Product < ApplicationRecord
has_tags :categories, transformer: CategoryTransformer
end
product.categories_list = "Electronics > Computers > Laptops"
Custom Normalization
module NormalizedTransformer
module_function
def parse_tags(tags)
tags = tags.split(',') unless tags.is_a?(Array)
tags.map do |tag|
tag.strip
.downcase
.gsub(/[^a-z0-9\s-]/, '') # Remove special chars
.gsub(/\s+/, '-') # Spaces to hyphens
end.uniq.compact
end
def recreate_string(tags)
tags.join(', ')
end
end
class Photo < ApplicationRecord
has_tags :labels, transformer: NormalizedTransformer
end
photo.labels_list = "Nature Photos, WILDLIFE shots, Outdoor-Photography"
# Transforms to: ["nature-photos", "wildlife-shots", "outdoor-photography"]
Context-Specific Transformers
Mix transformers based on tag context:
class Article < ApplicationRecord
include NoFlyList::TaggableRecord
has_tags :categories, transformer: CategoryTransformer
has_tags :hashtags, transformer: HashtagTransformer
has_tags :keywords, transformer: MultiLangTransformer
end
Testing Transformers
class TransformerTest < ActiveSupport::TestCase
test "hashtag parsing" do
input = "#ruby #rails doing #testing"
expected = ["ruby", "rails", "testing"]
assert_equal expected, HashtagTransformer.parse_tags(input)
end
test "hierarchical parsing" do
input = "Tech > Software > Tools"
expected = ["Tech", "Software", "Tools"]
assert_equal expected, CategoryTransformer.parse_tags(input)
end
end
Remember: Transformers are your first line of defense against messy tag data. Like TSA agents, they ensure only properly formatted tags make it through to your system.
Related Posts
Rails Version Management with Rails AppVersion
Rails AppVersion provides a standard way to handle version and environment information in Rails apps with best practices for deployment.
NoFlyList: How NoFlyList Optimizes Tag Queries
NoFlyList automatically detects your database type and uses specific optimization strategies to make tag queries blazingly fast.
NoFlyList: Choosing Between Polymorphic and Model-Specific Tags
Learn when to use polymorphic vs model-specific tags by building a blog platform. Understand the trade-offs and performance implications.