module Mongoid::TaggableWithContext::ClassMethods

Public Instance Methods

format_tags_for(context, value) click to toggle source

Helper method to convert a a tag input value of unknown type to a formatted array.

# File lib/mongoid/taggable_with_context.rb, line 106
def format_tags_for(context, value)
  return nil if value.nil?
  # 0) Tags must be an array or a string
  raise InvalidTagsFormat unless value.is_a?(Array) || value.is_a?(String)
  # 1) convert String to Array
  value = value.split(get_tag_separator_for(context)) if value.is_a? String
  # 2) remove all nil values
  # 3) strip all white spaces. Could leave blank strings (e.g. foo, , bar, baz)
  # 4) remove all blank strings
  # 5) remove duplicate
  value.compact.map(&:strip).reject(&:blank?).uniq
end
get_tag_group_by_field_for(context) click to toggle source
# File lib/mongoid/taggable_with_context.rb, line 83
def get_tag_group_by_field_for(context)
  self.taggable_with_context_options[context][:group_by_field]
end
get_tag_separator_for(context) click to toggle source
# File lib/mongoid/taggable_with_context.rb, line 79
def get_tag_separator_for(context)
  self.taggable_with_context_options[context][:separator]
end
tag_contexts() click to toggle source
# File lib/mongoid/taggable_with_context.rb, line 57
def tag_contexts
  self.taggable_with_context_options.keys
end
tag_database_fields() click to toggle source
# File lib/mongoid/taggable_with_context.rb, line 61
def tag_database_fields
  self.taggable_with_context_options.keys.map do |context|
    tag_options_for(context)[:db_field]
  end
end
tag_options_for(context) click to toggle source
# File lib/mongoid/taggable_with_context.rb, line 67
def tag_options_for(context)
  self.taggable_with_context_options[context]
end
taggable(*args) click to toggle source

Macro to declare a document class as taggable, specify field name for tags, and set options for tagging behavior.

@example Define a taggable document.

class Article
  include Mongoid::Document
  include Mongoid::TaggableWithContext
  taggable :keywords, separator: ' ', default: ['foobar']
end

@param [ Symbol ] field The name of the field for tags. Defaults to :tags if not specified. @param [ Hash ] options Options for taggable behavior.

@option options [ String ] :separator

The delimiter used when converting the tags to and from String format. Defaults to ' '

@option options [ :Symbol ] :group_by_field

The Mongoid field to group by when RealTimeGroupBy aggregation is used.

@option options [ <various> ] :default, :as, :localize, etc.

Options for Mongoid #field method will be automatically passed
to the underlying Array field
# File lib/mongoid/taggable_with_context.rb, line 45
def taggable(*args)
  # init variables
  options = args.extract_options!
  field = args.present? ? args.shift.to_sym : DEFAULT_FIELD
  added = add_taggable(field, options)
  # TODO: test if this is needed
  # descendants.each do |subclass|
  #   subclass.add_taggable(field, options)
  # end
  added
end
tagged_with(context, tags) click to toggle source

Find documents tagged with all tags passed as a parameter, given as an Array or a String using the configured separator.

@example Find matching all tags in an Array.

Article.tagged_with(['ruby', 'mongodb'])

@example Find matching all tags in a String.

Article.tagged_with('ruby, mongodb')

@param [ String ] :field The field name of the tag. @param [ Array<String, Symbol>, String ] :tags Tags to match. @return [ Criteria ] A new criteria.

# File lib/mongoid/taggable_with_context.rb, line 98
def tagged_with(context, tags)
  tags = format_tags_for(context, tags)
  field = tag_options_for(context)[:field]
  all_in(field => tags)
end
tags_for(context, group_by=nil, conditions={}) click to toggle source
# File lib/mongoid/taggable_with_context.rb, line 71
def tags_for(context, group_by=nil, conditions={})
  raise AggregationStrategyMissing
end
tags_with_weight_for(context, group_by=nil, conditions={}) click to toggle source
# File lib/mongoid/taggable_with_context.rb, line 75
def tags_with_weight_for(context, group_by=nil, conditions={})
  raise AggregationStrategyMissing
end

Protected Instance Methods

add_taggable(field, options) click to toggle source

Adds a taggable context to the list of contexts, and creates the underlying Mongoid field and alias methods for the context.

@param [ Symbol ] field The name of the Mongoid database field to store the taggable. @param [ Hash ] options The taggable options.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 128
def add_taggable(field, options)
  validate_taggable_options(options)

  # db_field: the field name stored in the database
  options[:db_field] = field.to_sym
  # field: the field name used to identify the tags. :field will
  # be identical to :db_field unless the :as option is specified
  options[:field] = options[:as] || field
  context = options[:field]
  options.reverse_merge!(
      separator: DEFAULT_SEPARATOR
  )

  # register / update settings
  self.taggable_with_context_options[options[:field]] = options

  create_taggable_mongoid_field(field, options)
  create_taggable_mongoid_index(context)
  define_taggable_accessors(context)
end
create_taggable_mongoid_field(name, options) click to toggle source

Creates the underlying Mongoid field for the tag context.

@param [ Symbol ] name The name of the Mongoid field. @param [ Hash ] options Options for the Mongoid field.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 175
def create_taggable_mongoid_field(name, options)
  field name, mongoid_field_options(options)
end
create_taggable_mongoid_index(name) click to toggle source

Creates an index for the underlying Mongoid field.

@param [ Symbol ] name The name or alias name of Mongoid field.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 196
def create_taggable_mongoid_index(name)
  index({ name => 1 }, { background: true })
end
define_class_group_by_getter(context) click to toggle source

Create the singleton getter method to retrieve the group_by field

@param [ Symbol ] context The name of the tag context.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 279
def define_class_group_by_getter(context)
  self.class.class_eval do
    define_method :"#{context}_group_by_field" do
      get_tag_group_by_field_for(context)
    end
  end
end
define_class_separator_getter(context) click to toggle source

Create the singleton getter method to retrieve the tag separator for a given context for all instances of the model.

@param [ Symbol ] context The name of the tag context.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 251
def define_class_separator_getter(context)
  self.class.class_eval do
    define_method :"#{context}_separator" do
      get_tag_separator_for(context)
    end
  end
end
define_class_tagged_with_getter(context) click to toggle source

Create the singleton getter method to retrieve the all instances of the model which contain the tag/tags for a given context.

@param [ Symbol ] context The name of the tag context.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 265
def define_class_tagged_with_getter(context)
  self.class.class_eval do
    define_method :"#{context}_tagged_with" do |tags|
      tagged_with(context, tags)
    end
  end
end
define_class_tags_getter(context) click to toggle source

Create the singleton getter method to retrieve all tags of a given context for all instances of the model.

@param [ Symbol ] context The name of the tag context.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 222
def define_class_tags_getter(context)
  # retrieve all tags ever created for the model
  self.class.class_eval do
    define_method context do |group_by = nil|
      tags_for(context, group_by)
    end
  end
end
define_class_weighted_tags_getter(context) click to toggle source

Create the singleton getter method to retrieve a weighted array of tags of a given context for all instances of the model.

@param [ Symbol ] context The name of the tag context.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 237
def define_class_weighted_tags_getter(context)
  self.class.class_eval do
    define_method :"#{context}_with_weight" do |group_by = nil|
      tags_with_weight_for(context, group_by)
    end
  end
end
define_instance_tag_setter(context) click to toggle source

Create the setter method for the provided taggable, using an alias method chain to the underlying field method.

@param [ Symbol ] context The name of the tag context.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 293
def define_instance_tag_setter(context)
  generated_methods.module_eval do
    alias_method "#{context}_without_taggable=", "#{context}="
    re_define_method("#{context}=") do |value|
      value = self.class.format_tags_for(context, value)
      self.send("#{context}_without_taggable=", value)
    end
    #alias_method_chain "#{context}=", :taggable
  end
end
define_instance_tag_string_getter(context) click to toggle source

Create the getter method for the joined tags string.

@param [ Symbol ] context The name of the tag context.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 309
def define_instance_tag_string_getter(context)
  generated_methods.module_eval do
    re_define_method("#{context}_string") do
      tag_string_for(context)
    end

    re_define_method("#{context}_string=") do |value|
      set_tag_string_for(context, value)
    end
  end
end
define_taggable_accessors(context) click to toggle source

Defines all accessor methods for the taggable context at both the instance and class level.

@param [ Symbol ] context The name of the tag context.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 206
def define_taggable_accessors(context)
  define_class_tags_getter(context)
  define_class_weighted_tags_getter(context)
  define_class_separator_getter(context)
  define_class_tagged_with_getter(context)
  define_class_group_by_getter(context)
  define_instance_tag_string_getter(context)
  define_instance_tag_setter(context)
end
mongoid_field_options(options = {}) click to toggle source

Prepares valid Mongoid option keys from the taggable options. Slices the taggable options to include only valid options for the Mongoid field method, and coerces :type to Array.

@param [ Hash ] :options The taggable options hash. @return [ Hash ] A options hash for the Mongoid field method.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 187
def mongoid_field_options(options = {})
  options.slice(*::Mongoid::Fields::Validators::Macro::OPTIONS).merge!(type: Array)
end
validate_taggable_options(options) click to toggle source

Validates the taggable options and raises errors if invalid options are detected.

@param [ Hash ] options The taggable options.

@since 1.1.1

# File lib/mongoid/taggable_with_context.rb, line 154
    def validate_taggable_options(options)
      if options[:field]
        raise <<-ERR
          taggable :field option has been removed as of version 1.1.1. Please use the
          syntax "taggable <database_name>, as: <tag_name>"
        ERR
      end
      if options[:string_method]
        raise <<-ERR
          taggable :string_method option has been removed as of version 1.1.1. Please
          define an alias to "<tags>_string" in your Model
        ERR
      end
    end