mongoid-urls 0.0.3

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b71d8482958f190295f9a8a0d52ca7cfdf8ef63c
4
+ data.tar.gz: 22b5ffff3481e0488d74b6b7f4743d7f6bb4fc80
5
+ SHA512:
6
+ metadata.gz: b263576272e13a2c1971355de8c28f5475d8a18aeef4e9a183c3d964a25e4ea43125b36d641b3ea5112eacec5bc088c2a0bb2f090d3c00a7aae171bf412ef9c3
7
+ data.tar.gz: fa31fde6011957d031e9b82cc9a3db6495c719c4c701f85c5b224a23e63710e6dd1f1cd56d92921f80a0b05d1b2532fc0ca75d6874fb6f50f1d70765019cec99
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --tty
2
+ --color
3
+ --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,23 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.1.1
6
+ - 2.2.2
7
+ - ruby-head
8
+ - jruby-19mode
9
+ - rbx-2
10
+
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: rbx-2
14
+
15
+ gemfile:
16
+ - Gemfile
17
+
18
+ services:
19
+ - mongodb
20
+
21
+ env: CI="travis"
22
+
23
+ script: "bundle exec rspec"
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'guard'
7
+ gem 'guard-rspec'
8
+ gem 'guard-rubocop'
9
+ gem 'rspec', '>= 3.2.0'
10
+ gem 'codeclimate-test-reporter', require: nil
11
+ gem 'mongoid-rspec', git: 'https://github.com/nofxx/mongoid-rspec'
12
+ end
data/Guardfile ADDED
@@ -0,0 +1,22 @@
1
+ # Note: The cmd option is now required due to the increasing number of ways
2
+ # rspec may be run, below are examples of the most common uses.
3
+ # * bundler: 'bundle exec rspec'
4
+ # * bundler binstubs: 'bin/rspec'
5
+ # * spring: 'bin/rsspec' (This will use spring if running and you have
6
+ # installed the spring binstubs per the docs)
7
+ # * zeus: 'zeus rspec' (requires the server to be started separetly)
8
+ # * 'just' rspec: 'rspec'
9
+
10
+ # guard :rubocop do
11
+ guard :rubocop, all_on_start: false, keep_failed: false, cli: ['-D'] do
12
+ watch(%r{.+\.rb$})
13
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
14
+ end
15
+
16
+ guard :rspec, cmd: 'bundle exec rspec' do
17
+ watch(%r{^spec/.+_spec\.rb$})
18
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
19
+ watch(/^generators\/(.+)\.rb$/) { |_m| 'spec/schemaless/worker_spec' }
20
+
21
+ watch('spec/spec_helper.rb') { 'spec' }
22
+ end
data/MIT-LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Marcos Piccinini
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.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ Mongoid::Urls
2
+ =============
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/mongoid-urls.png)](http://badge.fury.io/rb/mongoid-urls)
5
+ [![Dependency Status](https://gemnasium.com/nofxx/mongoid-urls.svg)](https://gemnasium.com/nofxx/mongoid-urls)
6
+ [![Build Status](https://secure.travis-ci.org/nofxx/mongoid-urls.png)](http://travis-ci.org/nofxx/mongoid-urls)
7
+ [![Code Climate](https://codeclimate.com/github/nofxx/mongoid-urls.png)](https://codeclimate.com/github/nofxx/mongoid-urls)
8
+ [![Coverage Status](https://coveralls.io/repos/nofxx/mongoid-urls/badge.svg)](https://coveralls.io/r/nofxx/mongoid-urls)
9
+
10
+ ## Mongoid::Urls
11
+
12
+ Simple slugs for mongoid models!
13
+
14
+
15
+ ## Short snappy token ids for Mongoid documents
16
+
17
+ This library is a quick and simple way to generate slugs
18
+ for your mongoid documents.
19
+
20
+ Mongoid::Urls can help turn this:
21
+
22
+ http://bestappever.com/video/4dcfbb3c6a4f1d4c4a000012
23
+
24
+ Into something more like this:
25
+
26
+ http://bestappever.com/video/kittens-playing-with-puppies
27
+
28
+
29
+ ## Getting started
30
+
31
+ In your gemfile, add:
32
+
33
+ gem 'mongoid-urls'
34
+
35
+ In your Mongoid documents, just add `include Mongoid::Urls` and the
36
+ `url` method will take care of all the setup, like so:
37
+
38
+ ```ruby
39
+ class Article
40
+ include Mongoid::Document
41
+ include Mongoid::Urls
42
+
43
+ field :title
44
+
45
+ url :title
46
+ end
47
+
48
+ ```
49
+
50
+ And that's it! There's some configuration options too - which are all
51
+ listed [below](#configuration).
52
+
53
+
54
+ ## Finders
55
+
56
+ `Mongoid::Urls` will **never** override `find`.
57
+ There's some helpers for custom fields:
58
+
59
+ ```ruby
60
+ Video.find_by_url("the-nice-url")
61
+ Account.find_by_url("acc-123456")
62
+ ```
63
+
64
+
65
+ ## Configuration
66
+
67
+ You may choose between two different systems for how your urls are stored:
68
+
69
+ Default #urls
70
+
71
+ Simple #url
72
+
73
+
74
+ #### Reserved
75
+
76
+
77
+ # Notes
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,3 @@
1
+ $: << File.expand_path("../../lib", __FILE__)
2
+
3
+ # Maybe benchmark stringex vs babosa just for fun...
@@ -0,0 +1,6 @@
1
+ module Mongoid
2
+ # Mongoid::Urls::VERSION
3
+ module Urls
4
+ VERSION = '0.0.3'
5
+ end
6
+ end
@@ -0,0 +1,82 @@
1
+ require 'mongoid'
2
+ require 'babosa'
3
+
4
+ module Mongoid
5
+ # Creates friendly urls for mongoid models!
6
+ module Urls
7
+ extend ActiveSupport::Concern
8
+ included do
9
+ cattr_accessor :reserved_words,
10
+ :url_simple,
11
+ :url_scope,
12
+ :url_key
13
+ end
14
+
15
+ # Methods avaiable at the model
16
+ module ClassMethods
17
+ #
18
+ # The #url
19
+ #
20
+ # url :title
21
+ #
22
+ # :simple -> Only one url per instance
23
+ # :reserve -> Defaults to %w( new edit )
24
+ #
25
+ def url(*args)
26
+ options = args.extract_options!
27
+ self.url_key = args.first.to_s
28
+ self.url_simple = options[:simple]
29
+ self.reserved_words = options[:reserve] || Set.new(%w(new edit))
30
+ create_url_fields
31
+ before_validation :create_urls
32
+ end
33
+
34
+ def find_by_url(u)
35
+ url_simple ? find_by(url: u) : find_by(urls: u)
36
+ rescue Mongoid::Errors::DocumentNotFound
37
+ nil
38
+ end
39
+
40
+ private
41
+
42
+ def create_url_fields
43
+ if url_simple
44
+ field :url, type: String
45
+ index({ url: 1 }, unique: true)
46
+ else
47
+ field :urls, type: Array, default: []
48
+ index(urls: 1)
49
+ end
50
+ end
51
+ end # ClassMethods
52
+
53
+ def to_param
54
+ urls.last
55
+ end
56
+
57
+ def slug
58
+ self[url_key].to_slug.normalize.to_s
59
+ end
60
+
61
+ protected
62
+
63
+ def validate_urls(u)
64
+ if self.class.find_by_url(u)
65
+ errors.add(:title, :uniqueness)
66
+ elsif reserved_words.include?(u)
67
+ errors.add(:title, :reserved)
68
+ else
69
+ true
70
+ end
71
+ end
72
+
73
+ def create_urls
74
+ return unless changes.include?(url_key)
75
+ validate_urls(new_url = slug)
76
+
77
+ return self.url = new_url if url_simple
78
+ urls << new_url
79
+ urls.uniq!
80
+ end
81
+ end # Urls
82
+ end # Mongoid
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'mongoid/urls/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'mongoid-urls'
7
+ s.version = Mongoid::Urls::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Marcos Piccinini']
10
+ s.homepage = 'http://github.com/nofxx/mongoid-urls'
11
+ s.licenses = ['MIT']
12
+ s.summary = 'A url sanitizer (slugs) for Mongoid documents.'
13
+ s.description = 'Mongoid Urls creates unique sanitized URLs for Mongoid documents. Simple and great for making URLs look good.'
14
+
15
+ s.rubyforge_project = 'mongoid-urls'
16
+ s.add_dependency 'mongoid', '> 4.0.0'
17
+ s.add_dependency 'babosa', '> 1.0.0'
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+ end
@@ -0,0 +1,193 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Urls do
4
+ let(:document_class) do
5
+ Object.send(:remove_const, :Document) if Object.const_defined?(:Document)
6
+ # A sample model
7
+ class Document
8
+ include Mongoid::Document
9
+ include Mongoid::Urls
10
+ field :title
11
+ end
12
+ Class.new(Document)
13
+ end
14
+
15
+ let(:document) do
16
+ document_class.create(title: "I'm a Document!")
17
+ end
18
+
19
+ let(:article) do
20
+ Article.new(title: "I'm an Article!")
21
+ end
22
+
23
+ describe '#slug' do
24
+ before(:each) { document_class.send(:url, :title) }
25
+ it 'should slugize a few stuff' do
26
+ expect(document.slug).to eq('im-a-document')
27
+ end
28
+
29
+ it 'should update slug' do
30
+ document.title = 'I "quoted"'
31
+ expect(document.slug).to eq('i-quoted')
32
+ end
33
+
34
+ it 'should keep old slugs' do
35
+ article.save
36
+ article.title = "Hello Ruby!"
37
+ article.save
38
+ expect(article.urls).to eq ["im-an-article", "hello-ruby"]
39
+ end
40
+ end
41
+
42
+ describe '#url' do
43
+ describe 'default "_id"' do
44
+ before(:each) { document_class.send(:url, :title) }
45
+
46
+ it 'should be created' do
47
+ expect(document).to have_field(:urls)
48
+ end
49
+
50
+ it 'should be valid' do
51
+ expect(document).to be_valid
52
+ end
53
+
54
+ it 'should be persisted' do
55
+ document.save
56
+ # why the anonymous #document_class doesn't work?
57
+ expect(Document.count).to eq(1)
58
+ end
59
+
60
+ it 'should create secondary index' do
61
+ expect(document.index_specifications).to_not be_empty
62
+ end
63
+ end
64
+
65
+ describe 'options' do
66
+ it 'should accept custom field names' do
67
+ document_class.send(:url, :sweet)
68
+ expect(document).to have_field(:urls)
69
+ end
70
+
71
+ it 'should not create custom finders with default id' do
72
+ # A sample model
73
+ class UntaintedDocument
74
+ include Mongoid::Document
75
+ include Mongoid::Urls
76
+ field :name
77
+ end
78
+ dc = Class.new(UntaintedDocument)
79
+
80
+ dc.send(:url, :name)
81
+ expect(dc.public_methods).to include(:find_by_url)
82
+ end
83
+
84
+ it 'should change `to_param`' do
85
+ document_class.send(:url, :title)
86
+ expect(document.to_param).to eq document.urls.first
87
+ end
88
+ end
89
+ end
90
+
91
+ describe 'callbacks' do
92
+ context 'when the article is a new record' do
93
+ it 'should create the urls after being saved' do
94
+ expect(article.urls).to be_empty
95
+ end
96
+
97
+ it 'should create the urls after being saved' do
98
+ article.save
99
+ expect(article.urls).to eq ['im-an-article']
100
+ end
101
+ end
102
+
103
+ context 'when the article is not a new record' do
104
+ it 'should not change the title after being saved' do
105
+ title_before = article.title
106
+ article.save
107
+ expect(article.title).to eq title_before
108
+ end
109
+
110
+ it 'should create a new title after being saved' do
111
+ article.title = 'Fresh new tomato'
112
+ article.save
113
+ expect(article.urls).to include 'fresh-new-tomato'
114
+ end
115
+
116
+ context 'when the article is initialized with a title' do
117
+ it 'should not change the title after being saved' do
118
+ title = 'test title'
119
+ expect(Article.create!(title: title).title).to eq title
120
+ end
121
+ end
122
+ end
123
+
124
+ context 'when the article is cloned' do
125
+ it 'should set the title to nil' do
126
+ d2 = article.clone
127
+ expect(d2.urls).to be_empty
128
+ end
129
+ end
130
+ end
131
+
132
+ describe 'finders' do
133
+ it 'should create a custom find method' do
134
+ document_class.send(:url, :title)
135
+ expect(document.class.public_methods).to include(:find_by_url)
136
+ end
137
+
138
+ it 'should find something with the custom find method' do
139
+ article.save
140
+ from_db = Article.find_by_url(article.urls.first)
141
+ expect(from_db.id).to eq(article.id)
142
+ end
143
+ end
144
+
145
+ describe '.to_param' do
146
+ it 'should respond with last valid url' do
147
+ document_class.send(:url, :title)
148
+ expect(document.to_param).to eq 'im-a-document'
149
+ end
150
+ end
151
+
152
+ describe '(no) collision resolution' do
153
+ before(:each) do
154
+ document_class.send(:url, :title)
155
+ document_class.create_indexes
156
+ end
157
+
158
+ context 'when creating a new record' do
159
+ it 'should raise when collisions can\'t be resolved on save' do
160
+ article.save
161
+ d2 = article.clone
162
+ expect(d2).to_not be_valid
163
+ expect(d2.save).to be_falsey
164
+ expect(d2.errors.messages).to include(:title)
165
+ end
166
+
167
+ it 'should raise when collisions can\'t be resolved on create!' do
168
+ article.title = '1234'
169
+ article.save
170
+ dup = Article.create(title: '1234')
171
+ expect(dup.errors.messages).to_not be_empty
172
+ end
173
+ end
174
+
175
+ context 'with other unique indexes present' do
176
+ before(:each) do
177
+ document_class.send(:field, :name)
178
+ document_class.send(:url, :name)
179
+ document_class.send(:index, { name: 1 }, unique: true)
180
+ document_class.create_indexes
181
+ end
182
+
183
+ context 'when violating the other index' do
184
+ it 'should raise an operation failure' do
185
+ duplicate_name = 'Got Duped.'
186
+ document_class.create!(name: duplicate_name)
187
+ expect { document_class.create!(name: duplicate_name) }
188
+ .to raise_exception(Mongo::Error::OperationFailure)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,40 @@
1
+ # require 'codeclimate-test-reporter'
2
+ # CodeClimate::TestReporter.start
3
+
4
+ $LOAD_PATH << File.expand_path('../../lib', __FILE__)
5
+
6
+ # require 'pry'
7
+ # require 'database_cleaner'
8
+ require 'mongoid'
9
+ require 'mongoid-rspec'
10
+
11
+ require 'mongoid/urls'
12
+
13
+ ENV['MONGOID_ENV'] = 'test'
14
+
15
+ Mongoid.configure do |config|
16
+ config.load_configuration(
17
+ clients: {
18
+ default: {
19
+ database: 'mongoid_urls_test',
20
+ hosts: ["localhost: #{ENV['BOXEN_MONGODB_PORT'] || 27_017}"],
21
+ options: {}
22
+ }
23
+ })
24
+ end
25
+
26
+ require 'support/models'
27
+
28
+ Mongo::Logger.logger.level = Logger::INFO
29
+
30
+ RSpec.configure do |config|
31
+ config.include Mongoid::Matchers
32
+
33
+ config.before(:each) do
34
+ Mongoid.purge!
35
+ end
36
+
37
+ config.after(:suite) do
38
+ puts "\n# With Mongoid v#{Mongoid::VERSION}"
39
+ end
40
+ end
@@ -0,0 +1,6 @@
1
+ class Article
2
+ include Mongoid::Document
3
+ include Mongoid::Urls
4
+ field :title
5
+ url :title
6
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid-urls
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Marcos Piccinini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mongoid
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: babosa
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.0
41
+ description: Mongoid Urls creates unique sanitized URLs for Mongoid documents. Simple
42
+ and great for making URLs look good.
43
+ email:
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".rspec"
50
+ - ".travis.yml"
51
+ - Gemfile
52
+ - Guardfile
53
+ - MIT-LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - benchmarks/benchmark.rb
57
+ - lib/mongoid/urls.rb
58
+ - lib/mongoid/urls/version.rb
59
+ - mongoid-urls.gemspec
60
+ - spec/mongoid/urls_spec.rb
61
+ - spec/spec_helper.rb
62
+ - spec/support/models.rb
63
+ homepage: http://github.com/nofxx/mongoid-urls
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project: mongoid-urls
83
+ rubygems_version: 2.4.7
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: A url sanitizer (slugs) for Mongoid documents.
87
+ test_files:
88
+ - spec/mongoid/urls_spec.rb
89
+ - spec/spec_helper.rb
90
+ - spec/support/models.rb