leifcr-mm-sluggable 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source :rubygems
2
+ gem 'rake'
3
+ gem 'bson_ext', '>= 1.6.4'
4
+ gem 'multi_json', '>= 1.3.6'
5
+
6
+ group :test do
7
+ # gem 'jnunemaker-matchy', '>= 0.4', :require => 'matchy'
8
+ # gem 'shoulda', '>= 3.1.1'
9
+ # gem 'mocha', '>= 0.12.3'
10
+ gem 'rspec'
11
+ gem 'database_cleaner', '>= 0.8.0'
12
+ end
13
+
14
+ group :development do
15
+ gem "wirble"
16
+ gem "hirb"
17
+ gem "awesome_print"
18
+ end
19
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2010 Richard Livsey
2
+ Copyright (c) 2012 Leif Ringstad
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,75 @@
1
+ = MongoMapper::Plugins::Sluggable
2
+
3
+ Add slugs to your fields. And use it for URLS...
4
+
5
+ == Usage
6
+
7
+ Either load it into all models, or individual models:
8
+
9
+ Add to all models
10
+ #initializers/mongo.rb
11
+ MongoMapper::Document.plugin(MongoMapper::Plugins::Sluggable)
12
+
13
+ Add to a specific model
14
+ #app/models/my_model.rb
15
+ plugin MongoMapper::Plugins::Sluggable
16
+
17
+ Then call sluggable to configure it
18
+ sluggable :title, :scope => :account_id
19
+
20
+ NOTE: The slugs will always be updated if you change the field it creates
21
+ the slugs from. see options to change behaviour
22
+
23
+ Free slugs will be reused
24
+ Example: you have my-title-1 and my-title-3 creating a new slug will generate my-title-2
25
+
26
+ Why always change slugs? Feels better to have same slug as title...
27
+
28
+ == Improve performance on your models
29
+
30
+ This is important to get fast queries! (you will regret if you don't add it...)
31
+
32
+ Read up on indexes here:
33
+ https://github.com/jnunemaker/mongomapper/issues/337
34
+
35
+ Easiest is to add db/indexes.rb to your app, then add this to that file:
36
+ # db/indexes.rb
37
+ MyModel.ensure_index(:slug_key)
38
+
39
+ == Options
40
+
41
+ Available options are:
42
+
43
+ * :scope - scope to a specific field (default - nil)
44
+ * :key - what the slug key is called (default - :slug) - NOTE, don't change this one
45
+ * :method - what method to call on the field to sluggify it (default - :parameterize)
46
+ * :callback - when to trigger the slugging (default - :before_validation_on_create)
47
+ * :always_update - Always update the slug on update/save/create etc.
48
+
49
+ Eg.
50
+
51
+ sluggable :title, :scope => :account_id, :key => :title_slug, :method => :to_url, :index => false
52
+
53
+ This will slug the title to the title_slug key, scoped to the account, will use String#to_url to slug it and won't add an index to the key
54
+
55
+ == Versioning
56
+
57
+ If an item with the same slug exists, it will add a version number to the slug.
58
+
59
+ IE assuming we already have an item with the slug of "monkey", the slug will be generated as "monkey-1"
60
+
61
+ == Note on Patches/Pull Requests
62
+ * Fork the project.
63
+ * Make your feature addition or bug fix.
64
+ * Add tests for it.
65
+
66
+ == Install
67
+ Bundler: (You are most likely using bundler in your app...)
68
+ gem 'mm-sluggable', :git => 'http://github.com/luuf/mm-sluggable.git'
69
+
70
+ == Thanks
71
+ * Richard Livsey for creating the original mm-sluggable
72
+ * John Nunemaker, Brandon Keepers & Others for MongoMapper
73
+
74
+ == Copyright
75
+ See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ require File.join(File.dirname(__FILE__), '/lib/sluggable/version')
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+ task :default => :spec
8
+
9
+ gemspec = eval(File.read("mm-sluggable.gemspec"))
@@ -0,0 +1,83 @@
1
+ require 'mongo_mapper'
2
+
3
+ module MongoMapper
4
+ module Plugins
5
+ module Sluggable
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def sluggable(to_slug = :title, options = {})
10
+ class_attribute :slug_options
11
+
12
+ self.slug_options = {
13
+ :to_slug => to_slug,
14
+ :key => :slug,
15
+ :method => :parameterize,
16
+ :scope => nil,
17
+ :max_length => 256,
18
+ :always_update => true, # allow always updating slug...
19
+ :callback => :before_validation,
20
+ :callback_on => nil,
21
+ }.merge(options)
22
+ key slug_options[:key], String
23
+
24
+ #before_validation :set_slug
25
+ self.send(slug_options[:callback], :set_slug, {:on => slug_options[:callback_on]}) if slug_options[:callback] && slug_options[:callback_on]
26
+ self.send(slug_options[:callback], :set_slug) if slug_options[:callback] && slug_options[:callback_on].nil?
27
+ end
28
+ end
29
+
30
+ def set_slug
31
+ options = self.class.slug_options
32
+
33
+ if options[:always_update] == false
34
+ return unless self.send(options[:key]).blank?
35
+ end
36
+
37
+ to_slug = self[options[:to_slug]]
38
+ return if to_slug.blank?
39
+
40
+ # previous_slug = self[:key]
41
+
42
+ the_slug = raw_slug = to_slug.send(options[:method]).to_s[0...options[:max_length]]
43
+
44
+ # no need to set, so return
45
+ return if (self.send(options[:key]) == the_slug)
46
+ # also do a regexp check,
47
+ # verify if the previous slug is "almost" the same as we want without digits/extras
48
+ return if (/(#{the_slug}-\d+)/.match(self.send(options[:key])) != nil)
49
+
50
+ conds = {}
51
+ conds[options[:key]] = the_slug
52
+ conds[options[:scope]] = self.send(options[:scope]) if options[:scope]
53
+
54
+ # first see if there is a equal slug
55
+ used_slugs = self.class.where(conds)
56
+ if (used_slugs.count > 0)
57
+ last_digit = 0 # zero for last one...
58
+ # if we are updating, check if the current slug is same as the one we want
59
+ conds[options[:key]] = /(#{the_slug}-\d+)/
60
+ used_slugs = self.class.where(conds).sort(options[:key].asc)
61
+ new_slug_set = false
62
+ used_slugs.each do |used_slug|
63
+ # get the last digit through regex
64
+ next_digit = used_slug.send(options[:key])[/(\d+)$/]
65
+ if (!next_digit.nil?)
66
+ # catch any numbers that are in between and free
67
+ if ((next_digit.to_i - last_digit.to_i) > 1)
68
+ the_slug = "#{raw_slug}-#{last_digit+1}"
69
+ new_slug_set = true
70
+ break # set a new slug, so all is good
71
+ end
72
+ last_digit = next_digit.to_i
73
+ # puts last_digit.inspect
74
+ end
75
+ end
76
+ the_slug = "#{raw_slug}-#{last_digit+1}" if new_slug_set == false
77
+ end
78
+
79
+ self.send(:"#{options[:key]}=", the_slug)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,3 @@
1
+ module Sluggable
2
+ VERSION = '0.2.5'
3
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leifcr-mm-sluggable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.5
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Leif Ringstad
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mongo_mapper
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.12.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: 0.12.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description:
47
+ email:
48
+ - leifcr@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - lib/mm-sluggable.rb
54
+ - lib/sluggable/version.rb
55
+ - Gemfile
56
+ - Rakefile
57
+ - LICENSE
58
+ - README.rdoc
59
+ homepage: http://github.com/leifcr/mm-sluggable
60
+ licenses: []
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 1.8.24
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: MongoMapper Plugin to store a slugged version of of a field.
83
+ test_files: []