mongoid-urls 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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