mongoid_taggable_with_context 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +6 -0
- data/Gemfile +0 -3
- data/README.md +190 -0
- data/Rakefile +1 -20
- data/VERSION +1 -1
- data/lib/mongoid/taggable_with_context.rb +5 -1
- data/mongoid_taggable_with_context.gemspec +9 -13
- data/spec/mongoid_taggable_with_context_spec.rb +21 -0
- metadata +25 -55
- data/README.rdoc +0 -174
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
mongoid_taggable_with_context
|
2
|
+
=============================
|
3
|
+
|
4
|
+
[![Build Status](https://secure.travis-ci.org/aq1018/mongoid_taggable_with_context.png?branch=master)](http://travis-ci.org/aq1018/mongoid_taggable_with_context) [![Dependency Status](https://gemnasium.com/aq1018/mongoid_taggable_with_context.png?travis)](https://gemnasium.com/aq1018/mongoid_taggable_with_context)
|
5
|
+
|
6
|
+
A tagging lib for Mongoid that allows for custom tagging along dynamic contexts. This gem was originally based on [mongoid_taggable](https://github.com/ches/mongoid_taggable) by Wilker Lúcio and Ches Martin. It has evolved substantially since that point, but all credit goes to them for the initial tagging functionality.
|
7
|
+
|
8
|
+
For instance, in a social network, a user might have tags that are called skills, interests, sports, and more. There is no real way to differentiate between tags and so an implementation of this type is not possible with `mongoid_taggable`.
|
9
|
+
|
10
|
+
Another example, aggregation such as counting tag occurrences was achieved by map-reduce with `mongoid_taggable`. It was ok for small amount of tags, but when the amount of tags and documents grow, the original `mongoid_taggable` won't be able to scale to real-time statistics demand.
|
11
|
+
|
12
|
+
Enter `mongoid_taggable_with_context`. Rather than tying functionality to a specific keyword (namely "tags"), `mongoid_taggable_with_context` allows you to specify an arbitrary number of *tag contexts* that can be used locally or in combination in the same way `mongoid_taggable` was used.
|
13
|
+
|
14
|
+
`mongoid_taggable_with_context` also provides flexibility on aggregation strategy. In addition to the map-reduce strategy, this gem also comes with real-time strategy. By using real-time strategy, your document can quickly adjusts the aggregation collection whenever tags are inserted or removed with $inc operator. So performance won't be impacted as the number of tags and documents grow.
|
15
|
+
|
16
|
+
Installation
|
17
|
+
------------
|
18
|
+
|
19
|
+
You can simply install from rubygems:
|
20
|
+
|
21
|
+
```
|
22
|
+
gem install mongoid_taggable_with_context
|
23
|
+
```
|
24
|
+
|
25
|
+
or in Gemfile:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
gem 'mongoid_taggable_with_context'
|
29
|
+
```
|
30
|
+
|
31
|
+
Basic Usage
|
32
|
+
-----------
|
33
|
+
|
34
|
+
To make a document taggable you need to include Mongoid::TaggableOnContext into your document and call the *taggable* macro with optional arguments:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
class Post
|
38
|
+
include Mongoid::Document
|
39
|
+
include Mongoid::TaggableWithContext
|
40
|
+
|
41
|
+
field :title
|
42
|
+
field :content
|
43
|
+
|
44
|
+
# default context is 'tags'.
|
45
|
+
# This creates #tags, #tags=, #tags_array, #tags_array= instance methods
|
46
|
+
# separator is " " by default
|
47
|
+
# #tags method returns space separated string
|
48
|
+
# #tags= methods accepts space separated string
|
49
|
+
# #tags_array method returns an array of tags
|
50
|
+
# #tags_array= method accepts an array of tags
|
51
|
+
# #tags and #tags_array are automatically synched.
|
52
|
+
taggable
|
53
|
+
|
54
|
+
# tagging for 'interests' context.
|
55
|
+
# This creates #interests, #interests=, #interests_array, #interests_array= instance methods
|
56
|
+
taggable :interests
|
57
|
+
|
58
|
+
# tagging for 'skills' context.
|
59
|
+
# This creates #skills, #skills=, #skills_array, #skills_array= instance methods
|
60
|
+
# changing tag separator to "," (Default is " ")
|
61
|
+
taggable :skills, :separator => ','
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
Then in your form, for example:
|
66
|
+
|
67
|
+
```rhtml
|
68
|
+
<% form_for @post do |f| %>
|
69
|
+
<p>
|
70
|
+
<%= f.label :title %><br />
|
71
|
+
<%= f.text_field :title %>
|
72
|
+
</p>
|
73
|
+
<p>
|
74
|
+
<%= f.label :content %><br />
|
75
|
+
<%= f.text_area :content %>
|
76
|
+
</p>
|
77
|
+
<p>
|
78
|
+
<%= f.label :tags %><br />
|
79
|
+
<%= text_field_tag 'post[tags]' %>
|
80
|
+
</p>
|
81
|
+
<p>
|
82
|
+
<%= f.label :interests %><br />
|
83
|
+
<%= text_field_tag 'post[interests]' %>
|
84
|
+
</p>
|
85
|
+
<p>
|
86
|
+
<%= f.label :skills %><br />
|
87
|
+
<%= text_field_tag 'post[skills]' %>
|
88
|
+
</p>
|
89
|
+
<p>
|
90
|
+
<button type="submit">Send</button>
|
91
|
+
</p>
|
92
|
+
<% end %>
|
93
|
+
```
|
94
|
+
|
95
|
+
Aggregation Strategies
|
96
|
+
----------------------
|
97
|
+
|
98
|
+
By including an aggregation strategy in your document, tag aggregations will be automatically available to you.
|
99
|
+
This lib presents the following aggregation strategies:
|
100
|
+
|
101
|
+
* MapReduce
|
102
|
+
* RealTime
|
103
|
+
|
104
|
+
The following document will automatically aggregate counts on all tag contexts.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
class Post
|
108
|
+
include Mongoid::Document
|
109
|
+
include Mongoid::TaggableWithContext
|
110
|
+
|
111
|
+
# automatically adds real time aggregations to all tag contexts
|
112
|
+
include Mongoid::TaggableWithContext::AggregationStrategy::RealTime
|
113
|
+
|
114
|
+
# alternatively for map-reduce
|
115
|
+
# include Mongoid::TaggableWithContext::AggregationStrategy::MapReduce
|
116
|
+
|
117
|
+
field :title
|
118
|
+
field :content
|
119
|
+
|
120
|
+
taggable
|
121
|
+
taggable :interests
|
122
|
+
taggable :skills, :separator => ','
|
123
|
+
end
|
124
|
+
```
|
125
|
+
|
126
|
+
When you include an aggregation strategy, your document also gains a few extra methods to retrieve aggregation data.
|
127
|
+
In the case of previous example the following methods are included:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
Post.tags
|
131
|
+
Post.tags_with_weight
|
132
|
+
Post.interests
|
133
|
+
Post.interests_with_weight
|
134
|
+
Post.skills
|
135
|
+
Post.skills_with_weight
|
136
|
+
```
|
137
|
+
|
138
|
+
Here is how to use these methods in more detail:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
Post.create!(:tags => "food,ant,bee")
|
142
|
+
Post.create!(:tags => "juice,food,bee,zip")
|
143
|
+
Post.create!(:tags => "honey,strip,food")
|
144
|
+
|
145
|
+
Post.tags # will retrieve ["ant", "bee", "food", "honey", "juice", "strip", "zip"]
|
146
|
+
Post.tags_with_weight # will retrieve:
|
147
|
+
# [
|
148
|
+
# ['ant', 1],
|
149
|
+
# ['bee', 2],
|
150
|
+
# ['food', 3],
|
151
|
+
# ['honey', 1],
|
152
|
+
# ['juice', 1],
|
153
|
+
# ['strip', 1],
|
154
|
+
# ['zip', 1]
|
155
|
+
# ]
|
156
|
+
```
|
157
|
+
|
158
|
+
Changing default separator
|
159
|
+
--------------------------
|
160
|
+
|
161
|
+
To change the default separator you may pass a *separator* argument to the macro:
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
class Post
|
165
|
+
include Mongoid::Document
|
166
|
+
include Mongoid::TaggableWithContext
|
167
|
+
|
168
|
+
field :title
|
169
|
+
field :content
|
170
|
+
|
171
|
+
taggable :separator => ',' # tags will be delineated by comma instead of space
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
Contributing to mongoid_taggable_with_context
|
176
|
+
-----------------------------------------------
|
177
|
+
|
178
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
179
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
180
|
+
* Fork the project
|
181
|
+
* Start a feature/bugfix branch
|
182
|
+
* Commit and push until you are happy with your contribution
|
183
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
184
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
185
|
+
|
186
|
+
Copyright
|
187
|
+
---------
|
188
|
+
|
189
|
+
Copyright (c) 2011 Aaron Qian. See LICENSE.txt for
|
190
|
+
further details.
|
data/Rakefile
CHANGED
@@ -28,26 +28,7 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
28
28
|
spec.rspec_opts = "--color --format progress"
|
29
29
|
end
|
30
30
|
|
31
|
-
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
32
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
-
spec.rcov = true
|
34
|
-
spec.rcov_opts = "--exclude ~\/.rvm,spec"
|
35
|
-
end
|
36
|
-
|
37
|
-
require 'reek/rake/task'
|
38
|
-
Reek::Rake::Task.new do |t|
|
39
|
-
t.fail_on_error = true
|
40
|
-
t.verbose = false
|
41
|
-
t.source_files = 'lib/**/*.rb'
|
42
|
-
end
|
43
|
-
|
44
|
-
require 'roodi'
|
45
|
-
require 'roodi_task'
|
46
|
-
RoodiTask.new do |t|
|
47
|
-
t.verbose = false
|
48
|
-
end
|
49
|
-
|
50
31
|
task :default => :spec
|
51
32
|
|
52
33
|
require 'yard'
|
53
|
-
YARD::Rake::YardocTask.new
|
34
|
+
YARD::Rake::YardocTask.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.1
|
@@ -10,6 +10,7 @@ module Mongoid::TaggableWithContext
|
|
10
10
|
self.context_array_to_context_hash = {}
|
11
11
|
delegate "convert_string_to_array", :to => 'self.class'
|
12
12
|
delegate "convert_array_to_string", :to => 'self.class'
|
13
|
+
delegate "clean_up_array", :to => 'self.class'
|
13
14
|
delegate "get_tag_separator_for", :to => 'self.class'
|
14
15
|
delegate "tag_contexts", :to => 'self.class'
|
15
16
|
delegate "tag_options_for", :to => 'self.class'
|
@@ -92,6 +93,9 @@ module Mongoid::TaggableWithContext
|
|
92
93
|
def #{tags_field}=(s)
|
93
94
|
write_attribute(:#{tags_array_field}, convert_string_to_array(s, get_tag_separator_for(:"#{tags_field}")))
|
94
95
|
end
|
96
|
+
def #{tags_array_field}=(ary)
|
97
|
+
write_attribute(:#{tags_array_field}, clean_up_array(ary))
|
98
|
+
end
|
95
99
|
END
|
96
100
|
end
|
97
101
|
|
@@ -149,7 +153,7 @@ module Mongoid::TaggableWithContext
|
|
149
153
|
end
|
150
154
|
|
151
155
|
def convert_array_to_string(ary = [], separator = " ")
|
152
|
-
|
156
|
+
ary.join(separator)
|
153
157
|
end
|
154
158
|
|
155
159
|
def clean_up_array(ary = [])
|
@@ -5,22 +5,23 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "mongoid_taggable_with_context"
|
8
|
-
s.version = "0.8.
|
8
|
+
s.version = "0.8.1"
|
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 = "
|
12
|
+
s.date = "2012-03-14"
|
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 = [
|
16
16
|
"LICENSE.txt",
|
17
|
-
"README.
|
17
|
+
"README.md"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
|
+
".travis.yml",
|
21
22
|
"Gemfile",
|
22
23
|
"LICENSE.txt",
|
23
|
-
"README.
|
24
|
+
"README.md",
|
24
25
|
"Rakefile",
|
25
26
|
"VERSION",
|
26
27
|
"init.rb",
|
@@ -37,6 +38,10 @@ Gem::Specification.new do |s|
|
|
37
38
|
s.require_paths = ["lib"]
|
38
39
|
s.rubygems_version = "1.8.10"
|
39
40
|
s.summary = "Mongoid taggable behaviour"
|
41
|
+
s.test_files = [
|
42
|
+
"spec/mongoid_taggable_with_context_spec.rb",
|
43
|
+
"spec/spec_helper.rb"
|
44
|
+
]
|
40
45
|
|
41
46
|
if s.respond_to? :specification_version then
|
42
47
|
s.specification_version = 3
|
@@ -50,9 +55,6 @@ Gem::Specification.new do |s|
|
|
50
55
|
s.add_development_dependency(%q<yard>, [">= 0"])
|
51
56
|
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
52
57
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
53
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
54
|
-
s.add_development_dependency(%q<reek>, [">= 0"])
|
55
|
-
s.add_development_dependency(%q<roodi>, [">= 0"])
|
56
58
|
else
|
57
59
|
s.add_dependency(%q<mongoid>, [">= 2.0.0"])
|
58
60
|
s.add_dependency(%q<database_cleaner>, [">= 0"])
|
@@ -62,9 +64,6 @@ Gem::Specification.new do |s|
|
|
62
64
|
s.add_dependency(%q<yard>, [">= 0"])
|
63
65
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
64
66
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
65
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
66
|
-
s.add_dependency(%q<reek>, [">= 0"])
|
67
|
-
s.add_dependency(%q<roodi>, [">= 0"])
|
68
67
|
end
|
69
68
|
else
|
70
69
|
s.add_dependency(%q<mongoid>, [">= 2.0.0"])
|
@@ -75,9 +74,6 @@ Gem::Specification.new do |s|
|
|
75
74
|
s.add_dependency(%q<yard>, [">= 0"])
|
76
75
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
77
76
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
78
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
79
|
-
s.add_dependency(%q<reek>, [">= 0"])
|
80
|
-
s.add_dependency(%q<roodi>, [">= 0"])
|
81
77
|
end
|
82
78
|
end
|
83
79
|
|
@@ -73,6 +73,27 @@ describe Mongoid::TaggableWithContext do
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
context "saving tags from array" do
|
77
|
+
before :each do
|
78
|
+
@m = MyModel.new
|
79
|
+
end
|
80
|
+
|
81
|
+
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]
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should remove nil tags from array" do
|
87
|
+
@m.tags_array = ["some", nil, "new", nil, "tags"]
|
88
|
+
@m.tags_array.should == %w[some new tags]
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should remove empty strings from array" do
|
92
|
+
@m.tags_array = ["some", "", "new", "", "tags"]
|
93
|
+
@m.tags_array.should == %w[some new tags]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
76
97
|
context "changing separator" do
|
77
98
|
before :all do
|
78
99
|
MyModel.tags_separator = ";"
|
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.
|
4
|
+
version: 0.8.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-03-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongoid
|
16
|
-
requirement: &
|
16
|
+
requirement: &22089400 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 2.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *22089400
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: database_cleaner
|
27
|
-
requirement: &
|
27
|
+
requirement: &22101640 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *22101640
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: bson
|
38
|
-
requirement: &
|
38
|
+
requirement: &22100100 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *22100100
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bson_ext
|
49
|
-
requirement: &
|
49
|
+
requirement: &22099180 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *22099180
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rspec
|
60
|
-
requirement: &
|
60
|
+
requirement: &22097660 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *22097660
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
|
-
requirement: &
|
71
|
+
requirement: &22112620 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *22112620
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: bundler
|
82
|
-
requirement: &
|
82
|
+
requirement: &22111660 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: 1.0.0
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *22111660
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: jeweler
|
93
|
-
requirement: &
|
93
|
+
requirement: &22111080 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,52 +98,20 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
102
|
-
- !ruby/object:Gem::Dependency
|
103
|
-
name: rcov
|
104
|
-
requirement: &70248022445860 !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ! '>='
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '0'
|
110
|
-
type: :development
|
111
|
-
prerelease: false
|
112
|
-
version_requirements: *70248022445860
|
113
|
-
- !ruby/object:Gem::Dependency
|
114
|
-
name: reek
|
115
|
-
requirement: &70248022445360 !ruby/object:Gem::Requirement
|
116
|
-
none: false
|
117
|
-
requirements:
|
118
|
-
- - ! '>='
|
119
|
-
- !ruby/object:Gem::Version
|
120
|
-
version: '0'
|
121
|
-
type: :development
|
122
|
-
prerelease: false
|
123
|
-
version_requirements: *70248022445360
|
124
|
-
- !ruby/object:Gem::Dependency
|
125
|
-
name: roodi
|
126
|
-
requirement: &70248022444840 !ruby/object:Gem::Requirement
|
127
|
-
none: false
|
128
|
-
requirements:
|
129
|
-
- - ! '>='
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: *70248022444840
|
101
|
+
version_requirements: *22111080
|
135
102
|
description: It provides some helpers to create taggable documents with context.
|
136
103
|
email: aq1018@gmail.com
|
137
104
|
executables: []
|
138
105
|
extensions: []
|
139
106
|
extra_rdoc_files:
|
140
107
|
- LICENSE.txt
|
141
|
-
- README.
|
108
|
+
- README.md
|
142
109
|
files:
|
143
110
|
- .document
|
111
|
+
- .travis.yml
|
144
112
|
- Gemfile
|
145
113
|
- LICENSE.txt
|
146
|
-
- README.
|
114
|
+
- README.md
|
147
115
|
- Rakefile
|
148
116
|
- VERSION
|
149
117
|
- init.rb
|
@@ -169,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
169
137
|
version: '0'
|
170
138
|
segments:
|
171
139
|
- 0
|
172
|
-
hash: -
|
140
|
+
hash: -3234920624644795753
|
173
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
142
|
none: false
|
175
143
|
requirements:
|
@@ -182,4 +150,6 @@ rubygems_version: 1.8.10
|
|
182
150
|
signing_key:
|
183
151
|
specification_version: 3
|
184
152
|
summary: Mongoid taggable behaviour
|
185
|
-
test_files:
|
153
|
+
test_files:
|
154
|
+
- spec/mongoid_taggable_with_context_spec.rb
|
155
|
+
- spec/spec_helper.rb
|
data/README.rdoc
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
= Mongoid Taggable With Context
|
2
|
-
|
3
|
-
A tagging lib for Mongoid that allows for custom tagging along dynamic contexts. This lib was originally based on Mongoid Taggable by Wilker Lúcio and Ches Martin. It has evolved substantially since that point, but all credit goes to them for the initial tagging functionality.
|
4
|
-
|
5
|
-
For instance, in a social network, a user might have tags that are called skills, interests, sports, and more. There is no real way to differentiate between tags and so an implementation of this type is not possible with Mongoid Taggable.
|
6
|
-
|
7
|
-
Another example, aggregation such as counting tag occurrences was achieved by map-reduce with Mongoid Taggable. It was ok for small amount of tags, but when the amount of tags and documents grow, the original Mongoid Taggable won't be able to scale to real-time statistics demand.
|
8
|
-
|
9
|
-
Enter Mongoid Taggable With Context. Rather than tying functionality to a specific keyword (namely "tags"), Mongoid Taggable With Context allows you to specify an arbitrary number of tag "contexts" that can be used locally or in combination in the same way Mongoid Taggable was used.
|
10
|
-
|
11
|
-
Mongoid Taggable With Context also provides flexibility on aggregation strategy. In addition to the map-reduce strategy, Mongoid Taggable With Context also comes with real-time strategy. By using real-time strategy, your document can quickly adjusts the aggregation collection whenever tags are inserted or removed with $inc operator. So performance won't be impacted as the number of tags and documents grow.
|
12
|
-
|
13
|
-
== Installation
|
14
|
-
|
15
|
-
You can simply install from rubygems:
|
16
|
-
|
17
|
-
gem install mongoid_taggable_with_context
|
18
|
-
|
19
|
-
or in Gemfile:
|
20
|
-
|
21
|
-
gem 'mongoid_taggable_with_context'
|
22
|
-
|
23
|
-
== Basic Usage
|
24
|
-
|
25
|
-
To make a document taggable you need to include Mongoid::TaggableOnContext into your document and call the *taggable* macro with optional arguments:
|
26
|
-
|
27
|
-
class Post
|
28
|
-
include Mongoid::Document
|
29
|
-
include Mongoid::TaggableWithContext
|
30
|
-
|
31
|
-
field :title
|
32
|
-
field :content
|
33
|
-
|
34
|
-
# default context is 'tags'.
|
35
|
-
# This creates #tags, #tags=, #tags_array, #tags_array= instance methods
|
36
|
-
# separator is " " by default
|
37
|
-
# #tags method returns space separated string
|
38
|
-
# #tags= methods accepts space separated string
|
39
|
-
# #tags_array method returns an array of tags
|
40
|
-
# #tags_array= method accepts an array of tags
|
41
|
-
# #tags and #tags_array are automatically synched.
|
42
|
-
taggable
|
43
|
-
|
44
|
-
# tagging for 'interests' context.
|
45
|
-
# This creates #interests, #interests=, #interests_array, #interests_array= instance methods
|
46
|
-
taggable :interests
|
47
|
-
|
48
|
-
# tagging for 'skills' context.
|
49
|
-
# This creates #skills, #skills=, #skills_array, #skills_array= instance methods
|
50
|
-
# changing tag separator to "," (Default is " ")
|
51
|
-
taggable :skills, :separator => ','
|
52
|
-
end
|
53
|
-
|
54
|
-
Then in your form, for example:
|
55
|
-
|
56
|
-
<% form_for @post do |f| %>
|
57
|
-
<p>
|
58
|
-
<%= f.label :title %><br />
|
59
|
-
<%= f.text_field :title %>
|
60
|
-
</p>
|
61
|
-
<p>
|
62
|
-
<%= f.label :content %><br />
|
63
|
-
<%= f.text_area :content %>
|
64
|
-
</p>
|
65
|
-
<p>
|
66
|
-
<%= f.label :tags %><br />
|
67
|
-
<%= text_field_tag 'post[tags]' %>
|
68
|
-
</p>
|
69
|
-
<p>
|
70
|
-
<%= f.label :interests %><br />
|
71
|
-
<%= text_field_tag 'post[interests]' %>
|
72
|
-
</p>
|
73
|
-
<p>
|
74
|
-
<%= f.label :skills %><br />
|
75
|
-
<%= text_field_tag 'post[skills]' %>
|
76
|
-
</p>
|
77
|
-
<p>
|
78
|
-
<button type="submit">Send</button>
|
79
|
-
</p>
|
80
|
-
<% end %>
|
81
|
-
|
82
|
-
|
83
|
-
== Aggregation Strategies
|
84
|
-
|
85
|
-
By including an aggregation strategy in your document, tag aggregations will be automatically available to you.
|
86
|
-
This lib presents the following aggregation strategies:
|
87
|
-
|
88
|
-
* MapReduce
|
89
|
-
* RealTime
|
90
|
-
|
91
|
-
The following document will automatically aggregate counts on all tag contexts.
|
92
|
-
|
93
|
-
class Post
|
94
|
-
include Mongoid::Document
|
95
|
-
include Mongoid::TaggableWithContext
|
96
|
-
|
97
|
-
# automatically adds real time aggregations to all tag contexts
|
98
|
-
include Mongoid::TaggableWithContext::AggregationStrategy::RealTime
|
99
|
-
|
100
|
-
# alternatively for map-reduce
|
101
|
-
# include Mongoid::TaggableWithContext::AggregationStrategy::MapReduce
|
102
|
-
|
103
|
-
field :title
|
104
|
-
field :content
|
105
|
-
|
106
|
-
taggable
|
107
|
-
taggable :interests
|
108
|
-
taggable :skills, :separator => ','
|
109
|
-
end
|
110
|
-
|
111
|
-
When you include an aggregation strategy, your document also gains a few extra methods to retrieve aggregation data.
|
112
|
-
In the case of previous example the following methods are included:
|
113
|
-
|
114
|
-
Post.tags
|
115
|
-
Post.tags_with_weight
|
116
|
-
Post.interests
|
117
|
-
Post.interests_with_weight
|
118
|
-
Post.skills
|
119
|
-
Post.skills_with_weight
|
120
|
-
|
121
|
-
Here is how to use these methods in more detail:
|
122
|
-
|
123
|
-
Post.create!(:tags => "food,ant,bee")
|
124
|
-
Post.create!(:tags => "juice,food,bee,zip")
|
125
|
-
Post.create!(:tags => "honey,strip,food")
|
126
|
-
|
127
|
-
Post.tags # will retrieve ["ant", "bee", "food", "honey", "juice", "strip", "zip"]
|
128
|
-
Post.tags_with_weight # will retrieve:
|
129
|
-
# [
|
130
|
-
# ['ant', 1],
|
131
|
-
# ['bee', 2],
|
132
|
-
# ['food', 3],
|
133
|
-
# ['honey', 1],
|
134
|
-
# ['juice', 1],
|
135
|
-
# ['strip', 1],
|
136
|
-
# ['zip', 1]
|
137
|
-
# ]
|
138
|
-
|
139
|
-
== Changing default separator
|
140
|
-
|
141
|
-
To change the default separator you may pass a *separator* argument to the macro:
|
142
|
-
|
143
|
-
class Post
|
144
|
-
include Mongoid::Document
|
145
|
-
include Mongoid::TaggableWithContext
|
146
|
-
|
147
|
-
field :title
|
148
|
-
field :content
|
149
|
-
|
150
|
-
taggable :separator => ',' # tags will be delineated by comma instead of space
|
151
|
-
end
|
152
|
-
|
153
|
-
== Development and Testing
|
154
|
-
|
155
|
-
Mongoid Taggable With Context uses Bundler for easy installation of development dependent gems.
|
156
|
-
To get all dependent gems for development, while inside mongoid_taggable_with_context directory:
|
157
|
-
|
158
|
-
bundle install
|
159
|
-
|
160
|
-
|
161
|
-
Mongoid Taggable With Context uses RSpec for its test coverage.
|
162
|
-
Inside mongoid_taggable_with_context directory, you can run the specs with:
|
163
|
-
|
164
|
-
rake spec
|
165
|
-
|
166
|
-
To see the test coverage, you need to be on ruby 1.8.7 (since latest rcov doesn't work 1.9)
|
167
|
-
and run the following command:
|
168
|
-
|
169
|
-
rake rcov
|
170
|
-
|
171
|
-
== Next Up
|
172
|
-
|
173
|
-
* More documentation.
|
174
|
-
* More Strategies. ( Let me know what kind of strategies you want, or contribute your own. )
|