mongoid-tags-arent-hard 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mongoid_delorean.gemspec
4
+ gemspec
5
+
6
+ gem "rspec"
7
+ gem 'database_cleaner'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Mark Bates
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,91 @@
1
+ # Mongoid::TagsArentHard
2
+
3
+ A tagging gem for Mongoid 3 that doesn't actually suck.
4
+
5
+ For some reason all of the tagging gems for Mongoid suck. Not sure why, it's really not that hard a problem to solve. One of the biggest complaints I have is that you can't have a model that has two types of "tags". The other problem I have with the other gems is that I want to be able to set my tags equal to a string and have it become an Array, and vice versa. This gem solves both of those problems.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'mongoid-tags-arent-hard'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install mongoid-tags-arent-hard
20
+
21
+ ## Usage
22
+
23
+ To add tags to a model you need to first include the <code>Mongoid::TagsArentHard</code> module and then define what you want the field to be called using the <code>taggable_with</code> method.
24
+
25
+ <pre><code>
26
+ class Foo
27
+ include Mongoid::Document
28
+ include Mongoid::TagsArentHard
29
+
30
+ taggable_with :tags
31
+ taggable_with :colors, separator: ";"
32
+ end
33
+ </code></pre>
34
+
35
+ Now we have two different types of "tags"; the first being called <code>tags</code> and the second being called <code>colors</code>. We have also told the <code>colors</code> to use <code>";"</code> as its separator.
36
+
37
+ Now we can do fun things like this:
38
+
39
+ <pre><code>
40
+ # set with either a string or an array:
41
+ foo = Foo.new(tags: "a,b,c", colors: ["red", "blue"])
42
+
43
+ # retrieve the list:
44
+ foo.tags #=> ["a", "b", "c"]
45
+ foo.colors #=> ["red", "blue"]
46
+
47
+ # append with either a string or an array:
48
+ foo.tags << "d"
49
+ foo.tags #=> ["a", "b", "c", "d"]
50
+ foo.colors << ["green", "yellow"]
51
+ foo.colors #=> ["red", "blue", "green", "yellow"]
52
+
53
+ # set with either a string or an array:
54
+ foo.tags = ["x", "y", "z"]
55
+ foo.tags #=> ["x", "y", "z"]
56
+ foo.colors = "black;brown"
57
+ foo.colors #=> ["black", "brown"]
58
+ </code></pre>
59
+
60
+ ### Searching
61
+
62
+ There are a few scopes included that make it easy to find objects that have the tags you are looking for. These methods are generated using the name of the field you designed, so in our previous example we would have the following methods available to us:
63
+
64
+ <pre><code>
65
+ # Find objects with any of the values:
66
+ Foo.with_any_tags("a")
67
+ Foo.with_any_tags(["a", "b"])
68
+ Foo.with_any_tags("a, b")
69
+ Foo.with_any_colors("a")
70
+ Foo.with_any_colors(["a", "b"])
71
+ Foo.with_any_colors("a, b")
72
+
73
+ # Find objects with all of these values:
74
+ Foo.with_all_tags("a")
75
+ Foo.with_all_tags(["a", "b"])
76
+ Foo.with_all_tags("a, b")
77
+ Foo.with_all_colors("a")
78
+ Foo.with_all_colors(["a", "b"])
79
+ Foo.with_all_colors("a, b")
80
+ </code></pre>
81
+
82
+ Again, notice that you can use either a string, an array, or a splatted list as values to these scopes.
83
+
84
+ ## Contributing
85
+
86
+ 1. Fork it
87
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
88
+ 3. Write your tests
89
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
90
+ 5. Push to the branch (`git push origin my-new-feature`)
91
+ 6. Create new Pull Request
@@ -0,0 +1,9 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ desc "Run tests"
5
+ task :default => [:ruby]
6
+
7
+ task :ruby do
8
+ system "bundle exec rspec"
9
+ end
@@ -0,0 +1,18 @@
1
+ require 'delegate'
2
+ require 'mongoid'
3
+ require "mongoid/tags_arent_hard/version"
4
+ require "mongoid/tags_arent_hard/configuration"
5
+ require "mongoid/tags_arent_hard/tags_arent_hard"
6
+ require "mongoid/tags_arent_hard/tags"
7
+
8
+ module Mongoid
9
+ module TagsArentHard
10
+
11
+ def self.config(&block)
12
+ @config ||= Configuration.new
13
+ yield @config if block_given?
14
+ return @config
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module Mongoid
2
+ module TagsArentHard
3
+ class Configuration
4
+ attr_accessor :separator
5
+
6
+ def initialize
7
+ self.separator = ","
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ module Mongoid
2
+ module TagsArentHard
3
+ class Tags
4
+
5
+ attr_accessor :tag_list
6
+ attr_accessor :options
7
+ delegate :join, :map, :each, :inspect, :==, :===, :eql?, :__bson_dump__, to: :tag_list
8
+
9
+ def initialize(*tag_list, options)
10
+ self.options = {separator: Mongoid::TagsArentHard.config.separator}.merge(options)
11
+ self.tag_list = []
12
+ self.<<(*tag_list)
13
+ end
14
+
15
+ def normalize(*tag_list)
16
+ tag_list.flatten.map {|s| s.split(self.options[:separator]).map {|x| x.strip}}.flatten
17
+ end
18
+
19
+ def <<(*tag_list)
20
+ self.tag_list << self.normalize(*tag_list)
21
+ self.tag_list.flatten!
22
+ self.tag_list.uniq!
23
+ return self.tag_list
24
+ end
25
+
26
+ def to_s
27
+ self.join(self.options[:separator])
28
+ end
29
+
30
+ def to_str
31
+ self.to_s
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,46 @@
1
+ module Mongoid
2
+ module TagsArentHard
3
+
4
+ def self.included(klass)
5
+ klass.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ def taggable_with(name, options = {})
11
+ options = {separator: Mongoid::TagsArentHard.config.separator}.merge(options)
12
+ self.field(name, type: Array, default: [])
13
+ self.class_eval do
14
+ define_method(name) do
15
+ val = super()
16
+ unless val.is_a?(Mongoid::TagsArentHard::Tags)
17
+ val = Mongoid::TagsArentHard::Tags.new(val, options)
18
+ self.send("#{name}=", val)
19
+ end
20
+ return val
21
+ end
22
+ define_method("#{name}=") do |val|
23
+ unless val.is_a?(Mongoid::TagsArentHard::Tags)
24
+ val = Mongoid::TagsArentHard::Tags.new(val, options)
25
+ end
26
+ super(val)
27
+ end
28
+
29
+ end
30
+ self.class.send(:define_method, "with_#{name}") do |*val|
31
+ self.send("with_any_#{name}", *val)
32
+ end
33
+
34
+ self.class.send(:define_method, "with_any_#{name}") do |*val|
35
+ any_in(name => Mongoid::TagsArentHard::Tags.new(*val, {}).tag_list)
36
+ end
37
+
38
+ self.class.send(:define_method, "with_all_#{name}") do |*val|
39
+ all_in(name => Mongoid::TagsArentHard::Tags.new(*val, {}).tag_list)
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,9 @@
1
+ module Mongoid
2
+ module Tags
3
+ module Arent
4
+ module Hard
5
+ VERSION = "1.0.0"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mongoid/tags_arent_hard/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "mongoid-tags-arent-hard"
8
+ gem.version = Mongoid::Tags::Arent::Hard::VERSION
9
+ gem.authors = ["Mark Bates"]
10
+ gem.email = ["mark@markbates.com"]
11
+ gem.description = %q{A tagging gem for Mongoid 3 that doesn't actually suck.}
12
+ gem.summary = %q{A tagging gem for Mongoid 3 that doesn't actually suck.}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency("mongoid", ">=3.0.0")
21
+ end
@@ -0,0 +1,6 @@
1
+ test:
2
+ sessions:
3
+ default:
4
+ database: mongoid_tags_arent_hard_test
5
+ hosts:
6
+ - localhost:27017
@@ -0,0 +1,23 @@
1
+ require 'bundler/setup'
2
+
3
+ require 'mongoid-tags-arent-hard' # and any other gems you need
4
+
5
+ require 'database_cleaner'
6
+
7
+ Mongoid.load!(File.join(File.dirname(__FILE__), "config.yml"), :test)
8
+ # require File.join(File.dirname(__FILE__), "support", "models")
9
+
10
+ DatabaseCleaner[:mongoid].strategy = :truncation
11
+
12
+ RSpec.configure do |config|
13
+
14
+ config.before(:each) do
15
+ DatabaseCleaner.clean
16
+ Mongoid::TagsArentHard.config.separator = ","
17
+ end
18
+
19
+ config.after(:each) do
20
+ Mongoid::TagsArentHard.config.separator = ","
21
+ end
22
+
23
+ end
@@ -0,0 +1,195 @@
1
+ require 'spec_helper'
2
+
3
+ class Foo
4
+ include Mongoid::Document
5
+ include Mongoid::TagsArentHard
6
+
7
+ taggable_with :tags
8
+ taggable_with :colors, separator: ";"
9
+ end
10
+
11
+ describe Mongoid::TagsArentHard do
12
+
13
+ let(:foo) { Foo.new }
14
+
15
+ {tags: ",", colors: ";"}.each do |_name, _separator|
16
+
17
+ describe ".taggable_with" do
18
+
19
+ it "defines a getter for '#{_name}'" do
20
+ foo.send(_name).should be_kind_of(Mongoid::TagsArentHard::Tags)
21
+ foo.send(_name).should eql([])
22
+ end
23
+
24
+ it "defines a setter for '#{_name}' (string)" do
25
+ foo.send("#{_name}=", "foo #{_separator} bar")
26
+ foo.send(_name).should eql(["foo","bar"])
27
+ end
28
+
29
+ it "defines a setter for '#{_name}' (array)" do
30
+ foo.send("#{_name}=", ["foo", "bar"])
31
+ foo.send(_name).should eql(["foo","bar"])
32
+ end
33
+
34
+ end
35
+
36
+ describe '#save' do
37
+
38
+ it "saves the #{_name} correctly" do
39
+ foo.send("#{_name}=", "foo#{_separator}bar")
40
+ foo.save!
41
+ foo.reload
42
+ foo.send(_name).should eql(["foo","bar"])
43
+ end
44
+
45
+ end
46
+
47
+ context 'class scopes' do
48
+
49
+ before(:each) do
50
+ @foo1 = Foo.create!(_name => "a#{_separator}b#{_separator}c")
51
+ @foo2 = Foo.create!(_name => "b#{_separator}c#{_separator}f")
52
+ @foo3 = Foo.create!(_name => "d#{_separator}e#{_separator}f")
53
+ end
54
+
55
+ describe "with_#{_name}" do
56
+
57
+ it "returns all models with a specific #{_name} (splatted)" do
58
+ results = Foo.send("with_#{_name}", "a")
59
+ results.should have(1).foo
60
+ results.should include(@foo1)
61
+
62
+ results = Foo.send("with_#{_name}", "b")
63
+ results.should have(2).foos
64
+ results.should include(@foo1)
65
+ results.should include(@foo2)
66
+ end
67
+
68
+ it "returns all models with a specific #{_name} (arrayed)" do
69
+ results = Foo.send("with_#{_name}", ["a"])
70
+ results.should have(1).foo
71
+ results.should include(@foo1)
72
+
73
+ results = Foo.send("with_#{_name}", ["b"])
74
+ results.should have(2).foos
75
+ results.should include(@foo1)
76
+ results.should include(@foo2)
77
+ end
78
+
79
+ end
80
+
81
+ describe "with_any_#{_name}" do
82
+
83
+ it "returns all models with any #{_name} (splatted)" do
84
+ results = Foo.send("with_any_#{_name}", "a")
85
+ results.should have(1).foo
86
+ results.should include(@foo1)
87
+
88
+ results = Foo.send("with_any_#{_name}", "b")
89
+ results.should have(2).foos
90
+ results.should include(@foo1)
91
+ results.should include(@foo2)
92
+
93
+ results = Foo.send("with_any_#{_name}", "a", "e")
94
+ results.should have(2).foos
95
+ results.should include(@foo1)
96
+ results.should include(@foo3)
97
+ end
98
+
99
+ it "returns all models with any #{_name} (arrayed)" do
100
+ results = Foo.send("with_any_#{_name}", ["a"])
101
+ results.should have(1).foo
102
+ results.should include(@foo1)
103
+
104
+ results = Foo.send("with_any_#{_name}", ["b"])
105
+ results.should have(2).foos
106
+ results.should include(@foo1)
107
+ results.should include(@foo2)
108
+
109
+ results = Foo.send("with_any_#{_name}", ["a", "e"])
110
+ results.should have(2).foos
111
+ results.should include(@foo1)
112
+ results.should include(@foo3)
113
+ end
114
+
115
+ it "returns all models with any #{_name} (string)" do
116
+ results = Foo.send("with_any_#{_name}", "a")
117
+ results.should have(1).foo
118
+ results.should include(@foo1)
119
+
120
+ results = Foo.send("with_any_#{_name}", "b")
121
+ results.should have(2).foos
122
+ results.should include(@foo1)
123
+ results.should include(@foo2)
124
+
125
+ results = Foo.send("with_any_#{_name}", "a,e")
126
+ results.should have(2).foos
127
+ results.should include(@foo1)
128
+ results.should include(@foo3)
129
+ end
130
+
131
+ end
132
+
133
+ describe "with_all_#{_name}" do
134
+
135
+ it "returns all models with all #{_name} (splatted)" do
136
+ results = Foo.send("with_all_#{_name}", "a")
137
+ results.should have(1).foo
138
+ results.should include(@foo1)
139
+
140
+ results = Foo.send("with_all_#{_name}", "b")
141
+ results.should have(2).foos
142
+ results.should include(@foo1)
143
+ results.should include(@foo2)
144
+
145
+ results = Foo.send("with_all_#{_name}", "a", "e")
146
+ results.should have(0).foos
147
+
148
+ results = Foo.send("with_all_#{_name}", "b", "f")
149
+ results.should have(1).foo
150
+ results.should include(@foo2)
151
+ end
152
+
153
+ it "returns all models with all #{_name} (arrayed)" do
154
+ results = Foo.send("with_all_#{_name}", ["a"])
155
+ results.should have(1).foo
156
+ results.should include(@foo1)
157
+
158
+ results = Foo.send("with_all_#{_name}", ["b"])
159
+ results.should have(2).foos
160
+ results.should include(@foo1)
161
+ results.should include(@foo2)
162
+
163
+ results = Foo.send("with_all_#{_name}", ["a", "e"])
164
+ results.should have(0).foos
165
+
166
+ results = Foo.send("with_all_#{_name}", ["b", "f"])
167
+ results.should have(1).foo
168
+ results.should include(@foo2)
169
+ end
170
+
171
+ it "returns all models with all #{_name} (string)" do
172
+ results = Foo.send("with_all_#{_name}", "a")
173
+ results.should have(1).foo
174
+ results.should include(@foo1)
175
+
176
+ results = Foo.send("with_all_#{_name}", "b")
177
+ results.should have(2).foos
178
+ results.should include(@foo1)
179
+ results.should include(@foo2)
180
+
181
+ results = Foo.send("with_all_#{_name}", "a,e")
182
+ results.should have(0).foos
183
+
184
+ results = Foo.send("with_all_#{_name}", "b,f")
185
+ results.should have(1).foo
186
+ results.should include(@foo2)
187
+ end
188
+
189
+ end
190
+
191
+ end
192
+
193
+ end
194
+
195
+ end
@@ -0,0 +1,66 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::TagsArentHard::Tags do
4
+
5
+ let(:tags) { Mongoid::TagsArentHard::Tags.new(%w{foo bar baz}, {}) }
6
+
7
+ after(:each) do
8
+ Mongoid::TagsArentHard.config.separator = ","
9
+ end
10
+
11
+ describe 'initialize' do
12
+
13
+ it "takes an array of tags" do
14
+ tags = Mongoid::TagsArentHard::Tags.new(["foo", "bar"], {})
15
+ tags.should eql(["foo", "bar"])
16
+ end
17
+
18
+ it "takes a splatted list" do
19
+ tags = Mongoid::TagsArentHard::Tags.new("foo", "bar", {})
20
+ tags.should eql(["foo", "bar"])
21
+ end
22
+
23
+ it "takes a string" do
24
+ tags = Mongoid::TagsArentHard::Tags.new("foo,bar", {})
25
+ tags.should eql(["foo", "bar"])
26
+ end
27
+
28
+ it "takes a string with a different separator" do
29
+ tags = Mongoid::TagsArentHard::Tags.new("foo bar", separator: " ")
30
+ tags.should eql(["foo", "bar"])
31
+ end
32
+
33
+ end
34
+
35
+ describe '<<' do
36
+
37
+ it "takes a string" do
38
+ tags << "fubar"
39
+ tags.should eql(["foo", "bar", "baz", "fubar"])
40
+
41
+ tags << "a,b"
42
+ tags.should eql(["foo", "bar", "baz", "fubar", "a", "b"])
43
+ end
44
+
45
+ it "takes an array" do
46
+ tags << ["a", "b"]
47
+ tags.should eql(["foo", "bar", "baz", "a", "b"])
48
+ end
49
+
50
+ it "should not allow duplicates" do
51
+ tags << "foo"
52
+ tags.should eql(["foo", "bar", "baz"])
53
+ end
54
+
55
+ end
56
+
57
+ describe 'to_s, to_str' do
58
+
59
+ it "returns a comma separated list of tags" do
60
+ tags.to_s.should eql("foo,bar,baz")
61
+ tags.to_str.should eql("foo,bar,baz")
62
+ end
63
+
64
+ end
65
+
66
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid-tags-arent-hard
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mark Bates
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mongoid
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
30
+ description: A tagging gem for Mongoid 3 that doesn't actually suck.
31
+ email:
32
+ - mark@markbates.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - LICENSE.txt
40
+ - README.md
41
+ - Rakefile
42
+ - lib/mongoid-tags-arent-hard.rb
43
+ - lib/mongoid/tags_arent_hard/configuration.rb
44
+ - lib/mongoid/tags_arent_hard/tags.rb
45
+ - lib/mongoid/tags_arent_hard/tags_arent_hard.rb
46
+ - lib/mongoid/tags_arent_hard/version.rb
47
+ - mongoid-tags-arent-hard.gemspec
48
+ - spec/config.yml
49
+ - spec/spec_helper.rb
50
+ - spec/tags_arent_hard/tags_arent_hard_spec.rb
51
+ - spec/tags_arent_hard/tags_spec.rb
52
+ homepage: ''
53
+ licenses: []
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 1.8.24
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: A tagging gem for Mongoid 3 that doesn't actually suck.
76
+ test_files:
77
+ - spec/config.yml
78
+ - spec/spec_helper.rb
79
+ - spec/tags_arent_hard/tags_arent_hard_spec.rb
80
+ - spec/tags_arent_hard/tags_spec.rb