mongoid_taggable_with_context 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -1,13 +1,13 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'mongoid', '>= 2.0.0'
3
+ gem 'mongoid', '>= 3.0.0'
4
4
 
5
5
  # Add dependencies to develop your gem here.
6
6
  # Include everything needed to run rake, tests, features, etc.
7
7
  group :development do
8
8
  gem 'database_cleaner'
9
- gem 'bson'
10
- gem 'bson_ext'
9
+ #gem 'bson'
10
+ #gem 'bson_ext'
11
11
  gem 'rspec'
12
12
  gem 'yard'
13
13
  gem 'bundler', '>= 1.0.0'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.1
1
+ 0.8.2
@@ -3,6 +3,8 @@ module Mongoid::TaggableWithContext
3
3
 
4
4
  class AggregationStrategyMissing < Exception; end
5
5
 
6
+ TAGGABLE_DEFAULT_SEPARATOR = ' '
7
+
6
8
  included do
7
9
  class_attribute :taggable_with_context_options
8
10
  class_attribute :context_array_to_context_hash
@@ -12,6 +14,7 @@ module Mongoid::TaggableWithContext
12
14
  delegate "convert_array_to_string", :to => 'self.class'
13
15
  delegate "clean_up_array", :to => 'self.class'
14
16
  delegate "get_tag_separator_for", :to => 'self.class'
17
+ delegate "format_tags_for_write", :to => 'self.class'
15
18
  delegate "tag_contexts", :to => 'self.class'
16
19
  delegate "tag_options_for", :to => 'self.class'
17
20
  delegate "tag_array_attributes", :to => 'self.class'
@@ -45,7 +48,7 @@ module Mongoid::TaggableWithContext
45
48
  options = args.extract_options!
46
49
  tags_field = (args.blank? ? :tags : args.shift).to_sym
47
50
  options.reverse_merge!(
48
- :separator => ' ',
51
+ :separator => TAGGABLE_DEFAULT_SEPARATOR,
49
52
  :array_field => "#{tags_field}_array".to_sym
50
53
  )
51
54
  tags_array_field = options[:array_field]
@@ -55,8 +58,11 @@ module Mongoid::TaggableWithContext
55
58
  self.context_array_to_context_hash[options[:array_field]] = tags_field
56
59
 
57
60
  # setup fields & indexes
58
- field tags_array_field, :type => Array, :default => []
59
- index tags_array_field
61
+ field tags_array_field, :type => Array, :default => options[:default]
62
+ # deprecated: index tags_array_field
63
+ # Invalid index specification on Category: tags_array, {}
64
+
65
+ index({ tags_array_field => 1 }, { background: true })
60
66
 
61
67
  # singleton methods
62
68
  class_eval <<-END
@@ -90,12 +96,10 @@ module Mongoid::TaggableWithContext
90
96
  def #{tags_field}
91
97
  convert_array_to_string(#{tags_array_field}, get_tag_separator_for(:"#{tags_field}"))
92
98
  end
93
- def #{tags_field}=(s)
94
- write_attribute(:#{tags_array_field}, convert_string_to_array(s, get_tag_separator_for(:"#{tags_field}")))
95
- end
96
- def #{tags_array_field}=(ary)
97
- write_attribute(:#{tags_array_field}, clean_up_array(ary))
99
+ def #{tags_field}=(value)
100
+ write_attribute(:#{tags_array_field}, format_tags_for_write(value, get_tag_separator_for(:"#{tags_field}")))
98
101
  end
102
+ alias_method :#{tags_array_field}=, :#{tags_field}=
99
103
  END
100
104
  end
101
105
 
@@ -126,7 +130,7 @@ module Mongoid::TaggableWithContext
126
130
  end
127
131
 
128
132
  def set_tag_separator_for(context, value)
129
- self.taggable_with_context_options[context][:separator] = value.nil? ? " " : value.to_s
133
+ self.taggable_with_context_options[context][:separator] = value.nil? ? TAGGABLE_DEFAULT_SEPARATOR : value.to_s
130
134
  end
131
135
 
132
136
  # Find documents tagged with all tags passed as a parameter, given
@@ -146,14 +150,25 @@ module Mongoid::TaggableWithContext
146
150
  all_in(array_field => tags)
147
151
  end
148
152
 
153
+ # Helper method to convert a a tag input value of unknown type
154
+ # to a formatted array.
155
+ def format_tags_for_write(value, separator = TAGGABLE_DEFAULT_SEPARATOR)
156
+ if value.is_a? Array
157
+ clean_up_array(value)
158
+ else
159
+ convert_string_to_array(value, separator)
160
+ end
161
+ end
162
+
149
163
  # Helper method to convert a String to an Array based on the
150
164
  # configured tag separator.
151
- def convert_string_to_array(str = "", separator = " ")
165
+ def convert_string_to_array(str = "", separator = TAGGABLE_DEFAULT_SEPARATOR)
152
166
  clean_up_array(str.split(separator))
153
167
  end
154
168
 
155
- def convert_array_to_string(ary = [], separator = " ")
156
- ary.join(separator)
169
+ def convert_array_to_string(ary = [], separator = TAGGABLE_DEFAULT_SEPARATOR)
170
+ #ary.join(separator)
171
+ (ary || []).join(separator)
157
172
  end
158
173
 
159
174
  def clean_up_array(ary = [])
@@ -163,5 +178,6 @@ module Mongoid::TaggableWithContext
163
178
  # 3). remove duplicate
164
179
  ary.compact.map(&:strip).reject(&:blank?).uniq
165
180
  end
181
+
166
182
  end
167
183
  end
@@ -9,21 +9,25 @@ module Mongoid::TaggableWithContext::AggregationStrategy
9
9
 
10
10
  module ClassMethods
11
11
  # Collection name for storing results of tag count aggregation
12
+
13
+ def aggregation_database_collection_for(context)
14
+ (@aggregation_database_collection ||= {})[context] ||= Moped::Collection.new(self.collection.database, aggregation_collection_for(context))
15
+ end
16
+
12
17
  def aggregation_collection_for(context)
13
18
  "#{collection_name}_#{context}_aggregation"
14
19
  end
15
-
20
+
16
21
  def tags_for(context, conditions={})
17
- conditions = {:sort => '_id'}.merge(conditions)
18
- db.collection(aggregation_collection_for(context)).find({:value => {"$gt" => 0 }}, conditions).to_a.map{ |t| t["_id"] }
22
+ aggregation_database_collection_for(context).find({:value => {"$gt" => 0 }}).sort(_id: 1).to_a.map{ |t| t["_id"] }
19
23
  end
20
24
 
21
25
  # retrieve the list of tag with weight(count), this is useful for
22
26
  # creating tag clouds
23
27
  def tags_with_weight_for(context, conditions={})
24
- conditions = {:sort => '_id'}.merge(conditions)
25
- db.collection(aggregation_collection_for(context)).find({:value => {"$gt" => 0 }}, conditions).to_a.map{ |t| [t["_id"], t["value"].to_i] }
28
+ aggregation_database_collection_for(context).find({:value => {"$gt" => 0 }}).sort(_id: 1).to_a.map{ |t| [t["_id"], t["value"].to_i] }
26
29
  end
30
+
27
31
  end
28
32
 
29
33
  protected
@@ -61,7 +65,7 @@ module Mongoid::TaggableWithContext::AggregationStrategy
61
65
  }
62
66
  END
63
67
 
64
- collection.master.map_reduce(map, reduce, :out => aggregation_collection_for(context))
68
+ self.class.map_reduce(map, reduce).out(replace: aggregation_collection_for(context)).time
65
69
  end
66
70
  end
67
- end
71
+ end
@@ -1,57 +1,107 @@
1
1
  module Mongoid::TaggableWithContext::AggregationStrategy
2
2
  module RealTime
3
3
  extend ActiveSupport::Concern
4
-
4
+
5
5
  included do
6
6
  set_callback :save, :after, :update_tags_aggregations_on_save
7
7
  set_callback :destroy, :after, :update_tags_aggregations_on_destroy
8
8
  end
9
9
 
10
10
  module ClassMethods
11
+ def tag_name_attribute
12
+ "_id"
13
+ end
14
+
11
15
  # Collection name for storing results of tag count aggregation
16
+
17
+ def aggregation_database_collection_for(context)
18
+ (@aggregation_database_collection ||= {})[context] ||= Moped::Collection.new(self.collection.database, aggregation_collection_for(context))
19
+ end
20
+
12
21
  def aggregation_collection_for(context)
13
22
  "#{collection_name}_#{context}_aggregation"
14
23
  end
15
-
24
+
16
25
  def tags_for(context, conditions={})
17
- conditions = {:sort => '_id'}.merge(conditions)
18
- db.collection(aggregation_collection_for(context)).find({:value => {"$gt" => 0 }}, conditions).to_a.map{ |t| t["_id"] }
26
+ aggregation_database_collection_for(context).find({:value => {"$gt" => 0 }}).sort(tag_name_attribute.to_sym => 1).to_a.map{ |t| t[tag_name_attribute] }
19
27
  end
20
28
 
21
29
  # retrieve the list of tag with weight(count), this is useful for
22
30
  # creating tag clouds
23
31
  def tags_with_weight_for(context, conditions={})
24
- conditions = {:sort => '_id'}.merge(conditions)
25
- db.collection(aggregation_collection_for(context)).find({:value => {"$gt" => 0 }}, conditions).to_a.map{ |t| [t["_id"], t["value"]] }
32
+ aggregation_database_collection_for(context).find({:value => {"$gt" => 0 }}).sort(tag_name_attribute.to_sym => 1).to_a.map{ |t| [t[tag_name_attribute], t["value"].to_i] }
33
+ end
34
+
35
+ def recalculate_all_context_tag_weights!
36
+ tag_contexts.each do |context|
37
+ recalculate_tag_weights!(context)
38
+ end
39
+ end
40
+
41
+ def recalculate_tag_weights!(context)
42
+ field = tag_options_for(context)[:array_field]
43
+
44
+ map = <<-END
45
+ function() {
46
+ if (!this.#{field})return;
47
+ for (index in this.#{field})
48
+ emit(this.#{field}[index], 1);
49
+ }
50
+ END
51
+
52
+ reduce = <<-END
53
+ function(key, values) {
54
+ var count = 0;
55
+ for (index in values) count += values[index];
56
+ return count;
57
+ }
58
+ END
59
+
60
+ self.map_reduce(map, reduce).out(replace: aggregation_collection_for(context)).time
61
+ end
62
+
63
+ # adapted from https://github.com/jesuisbonbon/mongoid_taggable/commit/42feddd24dedd66b2b6776f9694d1b5b8bf6903d
64
+ def tags_autocomplete(context, criteria, options={})
65
+ result = aggregation_database_collection_for(context).find({tag_name_attribute.to_sym => /^#{criteria}/})
66
+ result = result.sort(value: -1) if options[:sort_by_count] == true
67
+ result = result.limit(options[:max]) if options[:max] > 0
68
+ result.to_a.map{ |r| [r[tag_name_attribute], r["value"]] }
26
69
  end
27
70
  end
28
-
71
+
29
72
  protected
73
+
74
+ def get_conditions(context, tag)
75
+ {self.class.tag_name_attribute.to_sym => tag}
76
+ end
30
77
 
31
78
  def update_tags_aggregation(context_array_field, old_tags=[], new_tags=[])
32
79
  context = context_array_to_context_hash[context_array_field]
33
- coll = self.class.db.collection(self.class.aggregation_collection_for(context))
80
+ coll = self.class.aggregation_database_collection_for(context)
34
81
 
35
82
  old_tags ||= []
36
83
  new_tags ||= []
37
84
  unchanged_tags = old_tags & new_tags
38
85
  tags_removed = old_tags - unchanged_tags
39
86
  tags_added = new_tags - unchanged_tags
87
+
40
88
 
41
89
  tags_removed.each do |tag|
42
- coll.update({:_id => tag}, {'$inc' => {:value => -1}}, :upsert => true)
90
+ coll.find(get_conditions(context, tag)).upsert({'$inc' => {:value => -1}})
43
91
  end
44
-
45
92
  tags_added.each do |tag|
46
- coll.update({:_id => tag}, {'$inc' => {:value => 1}}, :upsert => true)
47
- end
93
+ coll.find(get_conditions(context, tag)).upsert({'$inc' => {:value => 1}})
94
+ end
95
+ #coll.find({_id: {"$in" => tags_removed}}).update({'$inc' => {:value => -1}}, [:upsert])
96
+ #coll.find({_id: {"$in" => tags_added}}).update({'$inc' => {:value => 1}}, [:upsert])
48
97
  end
49
98
 
50
99
  def update_tags_aggregations_on_save
100
+ indifferent_changes = HashWithIndifferentAccess.new changes
51
101
  tag_array_attributes.each do |context_array|
52
- next if changes[context_array].nil?
102
+ next if indifferent_changes[context_array].nil?
53
103
 
54
- old_tags, new_tags = changes[context_array]
104
+ old_tags, new_tags = indifferent_changes[context_array]
55
105
  update_tags_aggregation(context_array, old_tags, new_tags)
56
106
  end
57
107
  end
@@ -64,4 +114,4 @@ module Mongoid::TaggableWithContext::AggregationStrategy
64
114
  end
65
115
  end
66
116
  end
67
- end
117
+ end
@@ -0,0 +1,53 @@
1
+ module Mongoid::TaggableWithContext::GroupBy::AggregationStrategy
2
+ module RealTime
3
+ extend ActiveSupport::Concern
4
+ include Mongoid::TaggableWithContext::GroupBy::TaggableWithContext
5
+ include Mongoid::TaggableWithContext::AggregationStrategy::RealTime
6
+
7
+ module ClassMethods
8
+ def tag_name_attribute
9
+ "_name"
10
+ end
11
+
12
+ def tags_for(context, group_by, conditions={})
13
+ results = if group_by
14
+ query(context, group_by).to_a.map{ |t| t[tag_name_attribute] }
15
+ else
16
+ super(context, conditions)
17
+ end
18
+ results.uniq
19
+ end
20
+
21
+ def tags_with_weight_for(context, group_by, conditions={})
22
+ results = if group_by
23
+ query(context, group_by).to_a.map{ |t| [t[tag_name_attribute], t["value"].to_i] }
24
+ else
25
+ super(context, conditions)
26
+ end
27
+
28
+ tag_hash = {}
29
+ results.each do |tag, weight|
30
+ tag_hash[tag] ||= 0
31
+ tag_hash[tag] += weight
32
+ end
33
+ tag_hash.to_a
34
+ end
35
+
36
+ protected
37
+ def query(context, group_by)
38
+ aggregation_database_collection_for(context).find({:value => {"$gt" => 0 }, :group_by_field => group_by}).sort(tag_name_attribute.to_sym => 1)
39
+ end
40
+ end
41
+
42
+ protected
43
+
44
+ def get_conditions(context, tag)
45
+ conditions = {self.class.tag_name_attribute.to_sym => tag}
46
+ group_by_field = self.class.get_tag_group_by_field_for(context)
47
+ if group_by_field
48
+ conditions.merge!({:group_by_field => self.send(group_by_field)})
49
+ end
50
+ conditions
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ module Mongoid::TaggableWithContext::GroupBy
2
+ module TaggableWithContext
3
+ extend ActiveSupport::Concern
4
+ include Mongoid::TaggableWithContext
5
+
6
+ module ClassMethods
7
+ def taggable(*args)
8
+ super(*args)
9
+ args.extract_options!
10
+ tags_field = (args.blank? ? :tags : args.shift).to_sym
11
+ self.taggable_with_context_options[tags_field].reverse_merge!(:group_by_field => nil)
12
+
13
+ class_eval <<-END
14
+ class << self
15
+ def #{tags_field}(group_by=nil)
16
+ tags_for(:"#{tags_field}", group_by)
17
+ end
18
+
19
+ def #{tags_field}_with_weight(group_by=nil)
20
+ tags_with_weight_for(:"#{tags_field}", group_by)
21
+ end
22
+
23
+ def #{tags_field}_group_by_field
24
+ get_tag_group_by_field_for(:"#{tags_field}")
25
+ end
26
+ end
27
+ END
28
+ end
29
+
30
+ def tags_for(context, group_by, conditions={})
31
+ raise AggregationStrategyMissing
32
+ end
33
+
34
+ def tags_with_weight_for(context, group_by, conditions={})
35
+ raise AggregationStrategyMissing
36
+ end
37
+
38
+ def get_tag_group_by_field_for(context)
39
+ self.taggable_with_context_options[context][:group_by_field]
40
+ end
41
+ end
42
+ end
43
+ end
@@ -2,4 +2,6 @@ require 'active_support/concern'
2
2
 
3
3
  require File.join(File.dirname(__FILE__), 'mongoid/taggable_with_context')
4
4
  require File.join(File.dirname(__FILE__), 'mongoid/taggable_with_context/aggregation_strategy/map_reduce')
5
- require File.join(File.dirname(__FILE__), 'mongoid/taggable_with_context/aggregation_strategy/real_time')
5
+ require File.join(File.dirname(__FILE__), 'mongoid/taggable_with_context/aggregation_strategy/real_time')
6
+ require File.join(File.dirname(__FILE__), 'mongoid/taggable_with_context/group_by/taggable_with_context')
7
+ require File.join(File.dirname(__FILE__), 'mongoid/taggable_with_context/group_by/aggregation_strategy/real_time')
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "mongoid_taggable_with_context"
8
- s.version = "0.8.1"
8
+ s.version = "0.8.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Aaron Qian"]
12
- s.date = "2012-03-14"
12
+ s.date = "2012-09-01"
13
13
  s.description = "It provides some helpers to create taggable documents with context."
14
14
  s.email = "aq1018@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -28,6 +28,8 @@ Gem::Specification.new do |s|
28
28
  "lib/mongoid/taggable_with_context.rb",
29
29
  "lib/mongoid/taggable_with_context/aggregation_strategy/map_reduce.rb",
30
30
  "lib/mongoid/taggable_with_context/aggregation_strategy/real_time.rb",
31
+ "lib/mongoid/taggable_with_context/group_by/aggregation_strategy/real_time.rb",
32
+ "lib/mongoid/taggable_with_context/group_by/taggable_with_context.rb",
31
33
  "lib/mongoid_taggable_with_context.rb",
32
34
  "mongoid_taggable_with_context.gemspec",
33
35
  "spec/mongoid_taggable_with_context_spec.rb",
@@ -36,7 +38,7 @@ Gem::Specification.new do |s|
36
38
  s.homepage = "http://github.com/aq1018/mongoid_taggable_with_context"
37
39
  s.licenses = ["MIT"]
38
40
  s.require_paths = ["lib"]
39
- s.rubygems_version = "1.8.10"
41
+ s.rubygems_version = "1.8.24"
40
42
  s.summary = "Mongoid taggable behaviour"
41
43
  s.test_files = [
42
44
  "spec/mongoid_taggable_with_context_spec.rb",
@@ -47,29 +49,23 @@ Gem::Specification.new do |s|
47
49
  s.specification_version = 3
48
50
 
49
51
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
- s.add_runtime_dependency(%q<mongoid>, [">= 2.0.0"])
52
+ s.add_runtime_dependency(%q<mongoid>, [">= 3.0.0"])
51
53
  s.add_development_dependency(%q<database_cleaner>, [">= 0"])
52
- s.add_development_dependency(%q<bson>, [">= 0"])
53
- s.add_development_dependency(%q<bson_ext>, [">= 0"])
54
54
  s.add_development_dependency(%q<rspec>, [">= 0"])
55
55
  s.add_development_dependency(%q<yard>, [">= 0"])
56
56
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
57
57
  s.add_development_dependency(%q<jeweler>, [">= 0"])
58
58
  else
59
- s.add_dependency(%q<mongoid>, [">= 2.0.0"])
59
+ s.add_dependency(%q<mongoid>, [">= 3.0.0"])
60
60
  s.add_dependency(%q<database_cleaner>, [">= 0"])
61
- s.add_dependency(%q<bson>, [">= 0"])
62
- s.add_dependency(%q<bson_ext>, [">= 0"])
63
61
  s.add_dependency(%q<rspec>, [">= 0"])
64
62
  s.add_dependency(%q<yard>, [">= 0"])
65
63
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
66
64
  s.add_dependency(%q<jeweler>, [">= 0"])
67
65
  end
68
66
  else
69
- s.add_dependency(%q<mongoid>, [">= 2.0.0"])
67
+ s.add_dependency(%q<mongoid>, [">= 3.0.0"])
70
68
  s.add_dependency(%q<database_cleaner>, [">= 0"])
71
- s.add_dependency(%q<bson>, [">= 0"])
72
- s.add_dependency(%q<bson_ext>, [">= 0"])
73
69
  s.add_dependency(%q<rspec>, [">= 0"])
74
70
  s.add_dependency(%q<yard>, [">= 0"])
75
71
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
@@ -6,6 +6,7 @@ class MyModel
6
6
 
7
7
  taggable
8
8
  taggable :artists
9
+ taggable :albums, :default => []
9
10
  end
10
11
 
11
12
  class M1
@@ -26,7 +27,31 @@ class M2
26
27
  taggable :artists
27
28
  end
28
29
 
30
+ class M3
31
+ include Mongoid::Document
32
+ include Mongoid::TaggableWithContext::GroupBy::AggregationStrategy::RealTime
33
+
34
+ field :user
35
+ taggable :group_by_field => :user
36
+ taggable :artists, :group_by_field => :user
37
+ end
38
+
29
39
  describe Mongoid::TaggableWithContext do
40
+
41
+ context "default field value" do
42
+ before :each do
43
+ @m = MyModel.new
44
+ end
45
+
46
+ it "should be nil for artists" do
47
+ @m.changes['artists'].should be_nil
48
+ end
49
+
50
+ it "should be array for albums" do
51
+ @m.changes['albums_array'].should eql([nil, []])
52
+ end
53
+ end
54
+
30
55
  context "saving tags from plain text" do
31
56
  before :each do
32
57
  @m = MyModel.new
@@ -63,12 +88,12 @@ describe Mongoid::TaggableWithContext do
63
88
  end
64
89
 
65
90
  it "should remove repeated tags from array" do
66
- @m.tags_array = %w[some new tags some new tags]
91
+ @m.tags = %w[some new tags some new tags]
67
92
  @m.tags.should == "some new tags"
68
93
  end
69
94
 
70
95
  it "should remove nil tags from array" do
71
- @m.tags_array = ["some", nil, "new", nil, "tags"]
96
+ @m.tags = ["some", nil, "new", nil, "tags"]
72
97
  @m.tags.should == "some new tags"
73
98
  end
74
99
  end
@@ -79,17 +104,28 @@ describe Mongoid::TaggableWithContext do
79
104
  end
80
105
 
81
106
  it "should remove repeated tags from array" do
82
- @m.tags_array = %w[some new tags some new tags]
83
- @m.tags_array == %w[some new tags]
107
+ @m.tags = %w[some new tags some new tags]
108
+ @m.tags_array.should == %w[some new tags]
84
109
  end
85
110
 
86
111
  it "should remove nil tags from array" do
87
- @m.tags_array = ["some", nil, "new", nil, "tags"]
112
+ @m.tags = ["some", nil, "new", nil, "tags"]
88
113
  @m.tags_array.should == %w[some new tags]
89
114
  end
90
115
 
91
116
  it "should remove empty strings from array" do
92
- @m.tags_array = ["some", "", "new", "", "tags"]
117
+ @m.tags = ["some", "", "new", "", "tags"]
118
+ @m.tags_array.should == %w[some new tags]
119
+ end
120
+ end
121
+
122
+ context "saving tags from array using tags_array alias method" do
123
+ before :each do
124
+ @m = MyModel.new
125
+ end
126
+
127
+ it "should remove nil tags from array" do
128
+ @m.tags_array = ["some", nil, "new", nil, "tags"]
93
129
  @m.tags_array.should == %w[some new tags]
94
130
  end
95
131
  end
@@ -143,12 +179,22 @@ describe Mongoid::TaggableWithContext do
143
179
  end
144
180
 
145
181
  shared_examples_for "aggregation" do
146
- context "retriving index" do
182
+ context "retrieving index" do
183
+ context "when there's no tags'" do
184
+ it "should return an empty array" do
185
+ klass.tags.should == []
186
+ klass.artists.should == []
187
+
188
+ klass.tags_with_weight.should == []
189
+ klass.artists_with_weight == []
190
+ end
191
+ end
192
+
147
193
  context "on create directly" do
148
194
  before :each do
149
- klass.create!(:tags => "food ant bee", :artists => "jeff greg mandy aaron andy")
150
- klass.create!(:tags => "juice food bee zip", :artists => "grant andrew andy")
151
- klass.create!(:tags => "honey strip food", :artists => "mandy aaron andy")
195
+ klass.create!(:user => "user1", :tags => "food ant bee", :artists => "jeff greg mandy aaron andy")
196
+ klass.create!(:user => "user1", :tags => "juice food bee zip", :artists => "grant andrew andy")
197
+ klass.create!(:user => "user2", :tags => "honey strip food", :artists => "mandy aaron andy")
152
198
  end
153
199
 
154
200
  it "should retrieve the list of all saved tags distinct and ordered" do
@@ -227,9 +273,9 @@ describe Mongoid::TaggableWithContext do
227
273
 
228
274
  context "on create then update" do
229
275
  before :each do
230
- m1 = klass.create!(:tags => "food ant bee", :artists => "jeff greg mandy aaron andy")
231
- m2 = klass.create!(:tags => "juice food bee zip", :artists => "grant andrew andy")
232
- m3 = klass.create!(:tags => "honey strip food", :artists => "mandy aaron andy")
276
+ m1 = klass.create!(:user => "user1", :tags => "food ant bee", :artists => "jeff greg mandy aaron andy")
277
+ m2 = klass.create!(:user => "user1", :tags => "juice food bee zip", :artists => "grant andrew andy")
278
+ m3 = klass.create!(:user => "user2", :tags => "honey strip food", :artists => "mandy aaron andy")
233
279
 
234
280
  m1.tags_array = m1.tags_array + %w[honey strip shoe]
235
281
  m1.save!
@@ -270,9 +316,9 @@ describe Mongoid::TaggableWithContext do
270
316
 
271
317
  context "on create, update, then destroy" do
272
318
  before :each do
273
- m1 = klass.create!(:tags => "food ant bee", :artists => "jeff greg mandy aaron andy")
274
- m2 = klass.create!(:tags => "juice food bee zip", :artists => "grant andrew andy")
275
- m3 = klass.create!(:tags => "honey strip food", :artists => "mandy aaron andy")
319
+ m1 = klass.create!(:user => "user1", :tags => "food ant bee", :artists => "jeff greg mandy aaron andy")
320
+ m2 = klass.create!(:user => "user1", :tags => "juice food bee zip", :artists => "grant andrew andy")
321
+ m3 = klass.create!(:user => "user2", :tags => "honey strip food", :artists => "mandy aaron andy")
276
322
 
277
323
  m1.tags_array = m1.tags_array + %w[honey strip shoe] - %w[food]
278
324
  m1.save!
@@ -337,4 +383,65 @@ describe Mongoid::TaggableWithContext do
337
383
  klass.aggregation_collection_for(:artists).should == "m2s_artists_aggregation"
338
384
  end
339
385
  end
340
- end
386
+
387
+ context "realtime aggregation group by" do
388
+ let(:klass) { M3 }
389
+ it_should_behave_like "aggregation"
390
+
391
+ it "should generate the tags aggregation collection name correctly" do
392
+ klass.aggregation_collection_for(:tags).should == "m3s_tags_aggregation"
393
+ end
394
+
395
+ it "should generate the artists aggregation collection name correctly" do
396
+ klass.aggregation_collection_for(:artists).should == "m3s_artists_aggregation"
397
+ end
398
+
399
+ context "for groupings" do
400
+ before :each do
401
+ klass.create!(:user => "user1", :tags => "food ant bee", :artists => "jeff greg mandy aaron andy")
402
+ klass.create!(:user => "user1", :tags => "juice food bee zip", :artists => "grant andrew andy")
403
+ klass.create!(:user => "user2", :tags => "honey strip food", :artists => "mandy aaron andy")
404
+ end
405
+
406
+ it "should retrieve the list of all saved tags distinct and ordered" do
407
+ klass.tags("user1").should == %w[ant bee food juice zip]
408
+ klass.tags("user2").should == %w[food honey strip]
409
+
410
+ klass.artists("user1").should == %w[aaron andrew andy grant greg jeff mandy]
411
+ klass.artists("user2").should == %w[aaron andy mandy]
412
+ end
413
+
414
+ it "should retrieve a list of tags with weight" do
415
+ klass.tags_with_weight("user1").should == [
416
+ ['ant', 1],
417
+ ['bee', 2],
418
+ ['food', 2],
419
+ ['juice', 1],
420
+ ['zip', 1]
421
+ ]
422
+
423
+ klass.tags_with_weight("user2").should == [
424
+ ['food', 1],
425
+ ['honey', 1],
426
+ ['strip', 1]
427
+ ]
428
+
429
+ klass.artists_with_weight("user1").should == [
430
+ ['aaron', 1],
431
+ ['andrew', 1],
432
+ ['andy', 2],
433
+ ['grant', 1],
434
+ ['greg', 1],
435
+ ['jeff', 1],
436
+ ['mandy', 1]
437
+ ]
438
+
439
+ klass.artists_with_weight("user2").should == [
440
+ ['aaron', 1],
441
+ ['andy', 1],
442
+ ['mandy', 1]
443
+ ]
444
+ end
445
+ end
446
+ end
447
+ end
data/spec/spec_helper.rb CHANGED
@@ -17,5 +17,5 @@ RSpec.configure do |config|
17
17
  end
18
18
 
19
19
  Mongoid.configure do |config|
20
- config.master = Mongo::Connection.new.db("mongoid_taggable_with_context_test")
21
- end
20
+ config.connect_to("mongoid_taggable_with_context_test")
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_taggable_with_context
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,27 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-14 00:00:00.000000000 Z
12
+ date: 2012-09-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongoid
16
- requirement: &22089400 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 2.0.0
21
+ version: 3.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *22089400
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: database_cleaner
27
- requirement: &22101640 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,21 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *22101640
36
- - !ruby/object:Gem::Dependency
37
- name: bson
38
- requirement: &22100100 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
39
41
  none: false
40
42
  requirements:
41
43
  - - ! '>='
42
44
  - !ruby/object:Gem::Version
43
45
  version: '0'
44
- type: :development
45
- prerelease: false
46
- version_requirements: *22100100
47
46
  - !ruby/object:Gem::Dependency
48
- name: bson_ext
49
- requirement: &22099180 !ruby/object:Gem::Requirement
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
50
49
  none: false
51
50
  requirements:
52
51
  - - ! '>='
@@ -54,21 +53,15 @@ dependencies:
54
53
  version: '0'
55
54
  type: :development
56
55
  prerelease: false
57
- version_requirements: *22099180
58
- - !ruby/object:Gem::Dependency
59
- name: rspec
60
- requirement: &22097660 !ruby/object:Gem::Requirement
56
+ version_requirements: !ruby/object:Gem::Requirement
61
57
  none: false
62
58
  requirements:
63
59
  - - ! '>='
64
60
  - !ruby/object:Gem::Version
65
61
  version: '0'
66
- type: :development
67
- prerelease: false
68
- version_requirements: *22097660
69
62
  - !ruby/object:Gem::Dependency
70
63
  name: yard
71
- requirement: &22112620 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
72
65
  none: false
73
66
  requirements:
74
67
  - - ! '>='
@@ -76,10 +69,15 @@ dependencies:
76
69
  version: '0'
77
70
  type: :development
78
71
  prerelease: false
79
- version_requirements: *22112620
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
80
78
  - !ruby/object:Gem::Dependency
81
79
  name: bundler
82
- requirement: &22111660 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
83
81
  none: false
84
82
  requirements:
85
83
  - - ! '>='
@@ -87,10 +85,15 @@ dependencies:
87
85
  version: 1.0.0
88
86
  type: :development
89
87
  prerelease: false
90
- version_requirements: *22111660
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 1.0.0
91
94
  - !ruby/object:Gem::Dependency
92
95
  name: jeweler
93
- requirement: &22111080 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
94
97
  none: false
95
98
  requirements:
96
99
  - - ! '>='
@@ -98,7 +101,12 @@ dependencies:
98
101
  version: '0'
99
102
  type: :development
100
103
  prerelease: false
101
- version_requirements: *22111080
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
102
110
  description: It provides some helpers to create taggable documents with context.
103
111
  email: aq1018@gmail.com
104
112
  executables: []
@@ -118,6 +126,8 @@ files:
118
126
  - lib/mongoid/taggable_with_context.rb
119
127
  - lib/mongoid/taggable_with_context/aggregation_strategy/map_reduce.rb
120
128
  - lib/mongoid/taggable_with_context/aggregation_strategy/real_time.rb
129
+ - lib/mongoid/taggable_with_context/group_by/aggregation_strategy/real_time.rb
130
+ - lib/mongoid/taggable_with_context/group_by/taggable_with_context.rb
121
131
  - lib/mongoid_taggable_with_context.rb
122
132
  - mongoid_taggable_with_context.gemspec
123
133
  - spec/mongoid_taggable_with_context_spec.rb
@@ -135,9 +145,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
145
  - - ! '>='
136
146
  - !ruby/object:Gem::Version
137
147
  version: '0'
138
- segments:
139
- - 0
140
- hash: -3234920624644795753
141
148
  required_rubygems_version: !ruby/object:Gem::Requirement
142
149
  none: false
143
150
  requirements:
@@ -146,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
153
  version: '0'
147
154
  requirements: []
148
155
  rubyforge_project:
149
- rubygems_version: 1.8.10
156
+ rubygems_version: 1.8.24
150
157
  signing_key:
151
158
  specification_version: 3
152
159
  summary: Mongoid taggable behaviour