module Mongoid::Tracking::Aggregates::ClassMethods
Public Instance Methods
aggregate(name, &block)
click to toggle source
Defines an aggregate token to an already tracked model. It defines a new mongoid model named after the original model. Example: <tt>class Page</tt> <tt> include Mongoid::Document</tt> <tt> include Mongoid::Tracking</tt> <tt> track :visits</tt> <tt> aggregate :browsers do |b|</tt> <tt> b.split(" ").first</tt> <tt> end</tt> <tt>end</tt> A new model is defined as <tt>class PageAggregates</tt> This model has the following structure: <tt>belongs_to :page</tt> <tt>field :ns, :type => String</tt> <tt>field :key, :type => String</tt> <tt>index [:page_id, :ns, :key], :unique => true</tt> <tt>track :[original_parent_tracking_data]</tt> <tt>track :...</tt> :ns is the "namespace". It's the name you put along the "aggregate :browsers" in the original model definition. :key is your aggregation key. This is the value you are required to return in the "aggregate" block. With the above structure, you can always query aggregates directly
using Mongoid
this way:
<tt>TestModelAggregates.where(:ns => "browsers", :key => "explorer").first</tt> But you are encouraged to use Trackoid methods whenever possible.
# File lib/mongoid/tracking/aggregates.rb, line 60 def aggregate(name, &block) raise Errors::AggregationAlreadyDefined.new(self.name, name) if aggregate_fields.has_key? name raise Errors::AggregationNameDeprecated.new(name) if DEPRECATED_TOKENS.include? name.to_s define_aggregate_model if aggregate_klass.nil? has_many internal_accessor_name(name), class_name: aggregate_klass.to_s add_aggregate_field(name, block) create_aggregation_accessors(name) end
aggregated?()
click to toggle source
Return true if this model has aggregated data.
# File lib/mongoid/tracking/aggregates.rb, line 71 def aggregated? !aggregate_klass.nil? end
Protected Instance Methods
add_aggregate_field(name, block)
click to toggle source
Adds the aggregate field to the array of aggregated fields.
# File lib/mongoid/tracking/aggregates.rb, line 127 def add_aggregate_field(name, block) aggregate_fields[name] = block end
create_aggregation_accessors(name)
click to toggle source
# File lib/mongoid/tracking/aggregates.rb, line 144 def create_aggregation_accessors(name) # Aggregation accessors in the model acts like a named scopes define_method(name) do |*args| TrackerAggregates.new(self, name, args) end define_method("#{name}_with_track") do |track_field, *args| TrackerAggregates.new(self, name, args, track_field) end define_method("#{name}=") do raise NoMethodError end end
define_aggregate_model()
click to toggle source
Defines the aggregation model. It checks for class name conflicts
# File lib/mongoid/tracking/aggregates.rb, line 87 def define_aggregate_model unless defined?(Rails) && Rails.env.development? raise Errors::ClassAlreadyDefined.new(internal_aggregates_name) if foreign_class_defined? end parent = self define_klass do include Mongoid::Document include Mongoid::Tracking # Make the relation to the original class belongs_to parent.name.demodulize.underscore.to_sym, class_name: parent.name # Internal fields to track aggregation token and keys field :ns, type: String field :key, type: String index({ parent.name.foreign_key.to_sym => 1, ns: 1, key: 1 }, { unique: true, background: true }) # Include parent tracking data. parent.tracked_fields.each { |track_field| track track_field } end self.aggregate_klass = internal_aggregates_name.constantize end
define_klass(&block)
click to toggle source
Defines the aggregation external class. This class is named after the original class model but with “Aggregates” appended. Example: TestModel ==> TestModelAggregates
# File lib/mongoid/tracking/aggregates.rb, line 134 def define_klass(&block) scope = internal_aggregates_name.split('::') klass = scope.pop scope = scope.inject(Object) do |scope, const_name| scope.const_get(const_name) end klass = scope.const_set(klass, Class.new) klass.class_eval(&block) end
foreign_class_defined?()
click to toggle source
Returns true if there is a class defined with the same name as our aggregate class.
# File lib/mongoid/tracking/aggregates.rb, line 120 def foreign_class_defined? internal_aggregates_name.constantize && true rescue NameError false end
internal_accessor_name(name)
click to toggle source
# File lib/mongoid/tracking/aggregates.rb, line 82 def internal_accessor_name(name) (name.to_s + "_accessor").to_sym end
internal_aggregates_name()
click to toggle source
Returns the internal representation of the aggregates class name
# File lib/mongoid/tracking/aggregates.rb, line 77 def internal_aggregates_name str = self.to_s.underscore + "_aggregates" str.camelize end