friendly_id_sequel 3.0.0

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.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Norman Clarke
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ This is an in-development experimental adapter for
2
+ [FriendlyId](http://norman.github.com/friendly_id) using Sequel.
3
+
4
+ It currently supports all of FriendlyId's features except:
5
+
6
+ * Cached slugs
7
+ * Scoped slugs
8
+ * Rake tasks
9
+ * Rails Generator
10
+
11
+ Currently, only finds using `[]` are supported; I'll be adding some custom
12
+ filters to make working with slugged records easier if anybody ends up using
13
+ this.
14
+
15
+ @post = Post["this-is-a-title"]
16
+ @post.friendly_id # this-is-a-title
17
+
18
+ ## Usage
19
+
20
+ gem install friendly_id friendly_id_sequel
21
+
22
+ require "friendly_id"
23
+ require "friendly_id/sequel"
24
+
25
+ class Post < Sequel::Model
26
+ plugin :friendly_id :title, :use_slug => true
27
+ end
28
+
29
+
30
+ For more information on the available features, please see the
31
+ [FriendlyId Guide](http://norman.github.com/friendly_id/file.Guide.html).
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ require "rake"
2
+ require "rake/testtask"
3
+ require "rake/gempackagetask"
4
+ require "rake/clean"
5
+
6
+ CLEAN << "pkg" << "doc" << "coverage" << ".yardoc"
7
+
8
+ Rake::GemPackageTask.new(eval(File.read("friendly_id_sequel.gemspec"))) { |pkg| }
9
+ Rake::TestTask.new(:test) { |t| t.pattern = "test/*_test.rb" }
10
+
11
+ begin
12
+ require "yard"
13
+ YARD::Rake::YardocTask.new do |t|
14
+ t.options = ["--output-dir=docs"]
15
+ end
16
+ rescue LoadError
17
+ end
18
+
19
+ begin
20
+ require "rcov/rcovtask"
21
+ Rcov::RcovTask.new do |r|
22
+ r.test_files = FileList["test/**/*_test.rb"]
23
+ r.verbose = true
24
+ r.rcov_opts << "--exclude gems/*"
25
+ end
26
+ rescue LoadError
27
+ end
@@ -0,0 +1,27 @@
1
+ require "sequel/extensions/migration"
2
+
3
+ module FriendlyId
4
+ module SequelAdapter
5
+ class CreateSlugs < ::Sequel::Migration
6
+
7
+ def up
8
+ create_table :slugs do
9
+ primary_key :id, :type => Integer
10
+ string :name
11
+ integer :sluggable_id
12
+ integer :sequence, :null => false, :default => 1
13
+ string :sluggable_type, :limit => 40
14
+ string :scope
15
+ timestamp :created_at
16
+ end
17
+ add_index :slugs, :sluggable_id
18
+ add_index :slugs, [:name, :sluggable_type, :sequence, :scope], :name => "index_slugs_on_n_s_s_and_s", :unique => true
19
+ end
20
+
21
+ def down
22
+ drop_table :slugs
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,66 @@
1
+ module FriendlyId
2
+ module SequelAdapter
3
+
4
+ module SimpleModel
5
+
6
+ class SingleFinder
7
+
8
+ include FriendlyId::Finders::Base
9
+ include FriendlyId::Finders::Single
10
+
11
+ def find
12
+ with_sql(query).first if !unfriendly?
13
+ end
14
+
15
+ private
16
+
17
+ def query
18
+ table = simple_table
19
+ column = friendly_id_config.column
20
+ "SELECT * FROM #{table} WHERE #{column} = #{dataset.literal(id)}"
21
+ end
22
+
23
+ end
24
+
25
+ def self.included(base)
26
+ def base.primary_key_lookup(pk)
27
+ SingleFinder.new(pk, self).find or super
28
+ end
29
+ end
30
+
31
+ # Get the {FriendlyId::Status} after the find has been performed.
32
+ def friendly_id_status
33
+ @friendly_id_status ||= Status.new :record => self
34
+ end
35
+
36
+ # Returns the friendly_id.
37
+ def friendly_id
38
+ send self.class.friendly_id_config.column
39
+ end
40
+
41
+ # Returns the friendly id, or if none is available, the numeric id.
42
+ def to_param
43
+ (friendly_id || id).to_s
44
+ end
45
+
46
+ def validate
47
+ return if skip_friendly_id_validations
48
+ column = friendly_id_config.column
49
+ value = send(column)
50
+ return errors.add(column, "can't be blank") if value.blank?
51
+ return errors.add(column, "is reserved") if friendly_id_config.reserved?(value)
52
+ end
53
+
54
+ private
55
+
56
+ def skip_friendly_id_validations
57
+ friendly_id.nil? && self.class.friendly_id_config.allow_nil?
58
+ end
59
+
60
+ def friendly_id_config
61
+ self.class.friendly_id_config
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,43 @@
1
+ module FriendlyId
2
+ module SequelAdapter
3
+ class Slug < ::Sequel::Model
4
+
5
+ def to_friendly_id
6
+ sequence.to_i > 1 ? friendly_id_with_sequence : name
7
+ end
8
+
9
+ private
10
+
11
+ def before_create
12
+ self.sequence = next_sequence
13
+ self.created_at = DateTime.now
14
+ end
15
+
16
+ def enable_name_reversion
17
+ conditions = { :sluggable_id => sluggable_id, :sluggable_type => sluggable_type,
18
+ :name => name, :scope => scope }
19
+ self.class.filter(conditions).delete
20
+ end
21
+
22
+ def friendly_id_with_sequence
23
+ "#{name}#{separator}#{sequence}"
24
+ end
25
+
26
+ def next_sequence
27
+ enable_name_reversion
28
+ conditions = { :name => name, :scope => scope, :sluggable_type => sluggable_type }
29
+ prev = self.class.filter(conditions).order("sequence DESC").first
30
+ prev ? prev.sequence.succ : 1
31
+ end
32
+
33
+ def separator
34
+ sluggable_type.constantize.friendly_id_config.sequence_separator
35
+ end
36
+
37
+ def validate
38
+ errors.add(:name, "can't be blank") if name.blank?
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,84 @@
1
+ module FriendlyId
2
+ module SequelAdapter
3
+
4
+ module SluggedModel
5
+
6
+ class SingleFinder
7
+
8
+ include FriendlyId::Finders::Base
9
+ include FriendlyId::Finders::Single
10
+
11
+ def find
12
+ join(*join_conditions).select(columns).where(conditions).first
13
+ end
14
+
15
+ private
16
+
17
+ def columns
18
+ :"#{table_name}".*
19
+ end
20
+
21
+ def conditions
22
+ {:name.qualify("slugs") => name, :sequence.qualify("slugs") => sequence}
23
+ end
24
+
25
+ def join_conditions
26
+ return :slugs, :sluggable_id => :id, :sluggable_type => model_class.to_s
27
+ end
28
+
29
+ end
30
+
31
+ include FriendlyId::Slugged::Model
32
+
33
+ def self.included(base)
34
+ base.one_to_many :slugs,
35
+ :class => slug_class,
36
+ :key => "sluggable_id",
37
+ :conditions => {:sluggable_type => "#{base.to_s}"},
38
+ :order => "id DESC"
39
+ def base.[](*args)
40
+ if args.size == 1
41
+ SingleFinder.new(args.first, self).find or super
42
+ else
43
+ super
44
+ end
45
+ end
46
+ end
47
+
48
+ def self.slug_class
49
+ FriendlyId::SequelAdapter::Slug
50
+ end
51
+
52
+ def find_slug(name, sequence)
53
+ slugs_dataset.where("slugs.name" => name, "slugs.sequence" => sequence).first
54
+ end
55
+
56
+ private
57
+
58
+ def after_save
59
+ return if friendly_id_config.allow_nil? && !@slug
60
+ @slug.sluggable_id = id
61
+ @slug.save
62
+ end
63
+
64
+ def build_slug
65
+ self.slug = SluggedModel.slug_class.new :name => slug_text,
66
+ :sluggable_type => self.class.to_s
67
+ end
68
+
69
+ def skip_friendly_id_validations
70
+ friendly_id.nil? && friendly_id_config.allow_nil?
71
+ end
72
+
73
+ def validate
74
+ build_slug if new_slug_needed?
75
+ method = friendly_id_config.method
76
+ rescue FriendlyId::BlankError
77
+ return errors.add(method, "can't be blank")
78
+ rescue FriendlyId::ReservedError
79
+ return errors.add(method, "is reserved")
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,11 @@
1
+ module FriendlyId
2
+ module SequelAdapter
3
+ module Version
4
+ MAJOR = 3
5
+ MINOR = 0
6
+ TINY = 0
7
+ STRING = [MAJOR, MINOR, TINY].join(".")
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,33 @@
1
+ require "sequel"
2
+ require File.join(File.dirname(__FILE__), "friendly_id", "sequel_adapter", "simple_model")
3
+ require File.join(File.dirname(__FILE__), "friendly_id", "sequel_adapter", "slugged_model")
4
+ require File.join(File.dirname(__FILE__), "friendly_id", "sequel_adapter", "create_slugs")
5
+
6
+ module Sequel
7
+
8
+ module Plugins
9
+
10
+ module FriendlyId
11
+
12
+ def self.configure(model, method, opts={})
13
+ model.instance_eval do
14
+ if friendly_id_config.use_slug?
15
+ require File.join(File.dirname(__FILE__), "friendly_id", "sequel_adapter", "slug")
16
+ include ::FriendlyId::SequelAdapter::SluggedModel
17
+ else
18
+ include ::FriendlyId::SequelAdapter::SimpleModel
19
+ end
20
+ end
21
+ end
22
+
23
+ module ClassMethods
24
+ attr_accessor :friendly_id_config
25
+ def friendly_id_config
26
+ @friendly_id_config ||= ::FriendlyId::Configuration.new(self, *friendly_id_opts)
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ module FriendlyId
4
+ module Test
5
+ module SequelAdapter
6
+
7
+ # Tests for Sequel models using FriendlyId without slugs.
8
+ class BasicSimpleTest < ::Test::Unit::TestCase
9
+ include FriendlyId::Test::Generic
10
+ include FriendlyId::Test::Simple
11
+ include FriendlyId::Test::SequelAdapter::Core
12
+ include FriendlyId::Test::SequelAdapter::Simple
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ module FriendlyId
4
+ module Test
5
+ module SequelAdapter
6
+
7
+ # Tests for Sequel models using FriendlyId with slugs.
8
+ class BasicSluggedTest < ::Test::Unit::TestCase
9
+ include FriendlyId::Test::Generic
10
+ include FriendlyId::Test::Slugged
11
+ include FriendlyId::Test::SequelAdapter::Core
12
+ include FriendlyId::Test::SequelAdapter::Slugged
13
+ end
14
+ end
15
+ end
16
+ end
data/test/core.rb ADDED
@@ -0,0 +1,39 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ module FriendlyId
4
+ module Test
5
+ module SequelAdapter
6
+
7
+ # Core tests for any sequel model using FriendlyId.
8
+ module Core
9
+
10
+ def teardown
11
+ klass.delete
12
+ other_class.delete
13
+ FriendlyId::SequelAdapter::Slug.delete
14
+ end
15
+
16
+ def find_method
17
+ :[]
18
+ end
19
+
20
+ def create_method
21
+ :create
22
+ end
23
+
24
+ def delete_all_method
25
+ :destroy
26
+ end
27
+
28
+ def save_method
29
+ :save
30
+ end
31
+
32
+ def validation_exceptions
33
+ ::Sequel::ValidationFailed
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ module FriendlyId
4
+ module Test
5
+ module SequelAdapter
6
+
7
+ class CustomNormalizerTest < ::Test::Unit::TestCase
8
+
9
+ include FriendlyId::Test::SequelAdapter::Core
10
+ include FriendlyId::Test::SequelAdapter::Slugged
11
+ include FriendlyId::Test::CustomNormalizer
12
+
13
+ def klass
14
+ Person
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
data/test/simple.rb ADDED
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ module FriendlyId
4
+ module Test
5
+ module SequelAdapter
6
+
7
+ module Simple
8
+
9
+ def klass
10
+ User
11
+ end
12
+
13
+ def other_class
14
+ Book
15
+ end
16
+
17
+ def instance
18
+ @instance ||= klass.send(create_method, :name => "hello world")
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
data/test/slugged.rb ADDED
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ module FriendlyId
4
+ module Test
5
+ module SequelAdapter
6
+
7
+ module Slugged
8
+
9
+ def klass
10
+ Post
11
+ end
12
+
13
+ def other_class
14
+ City
15
+ end
16
+
17
+ def instance
18
+ @instance ||= klass.send(create_method, :name => "hello world")
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
data/test/sti_test.rb ADDED
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ module FriendlyId
4
+ module Test
5
+ module SequelAdapter
6
+
7
+ class StiTest < ::Test::Unit::TestCase
8
+
9
+ include FriendlyId::Test::Generic
10
+ include FriendlyId::Test::Slugged
11
+ include FriendlyId::Test::SequelAdapter::Core
12
+ include FriendlyId::Test::SequelAdapter::Slugged
13
+
14
+ def klass
15
+ Cat
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,63 @@
1
+ begin
2
+ # Try to require the preresolved locked set of gems.
3
+ require File.join(File.dirname(__FILE__), "..", ".bundle", "environment")
4
+ rescue LoadError
5
+ # Fall back on doing an unlocked resolve at runtime.
6
+ require "rubygems"
7
+ require "bundler"
8
+ Bundler.setup
9
+ end
10
+
11
+ require "sequel"
12
+ require "active_support"
13
+ require "friendly_id"
14
+ require "friendly_id/test"
15
+ require "logger"
16
+ require "test/unit"
17
+ require "mocha"
18
+
19
+ require File.dirname(__FILE__) + "/../lib/friendly_id_sequel"
20
+ require File.dirname(__FILE__) + "/core"
21
+ require File.dirname(__FILE__) + "/simple"
22
+ require File.dirname(__FILE__) + "/slugged"
23
+
24
+ DB = Sequel.sqlite
25
+ FriendlyId::SequelAdapter::CreateSlugs.apply(DB, :up)
26
+
27
+ %w[books users].each do |table|
28
+ DB.create_table(table) do
29
+ primary_key :id, :type => Integer
30
+ string :name, :unique => true
31
+ string :note
32
+ end
33
+ end
34
+
35
+ class Book < Sequel::Model; end
36
+ class User < Sequel::Model; end
37
+ [Book, User].each do |klass|
38
+ klass.plugin :friendly_id, :name
39
+ end
40
+
41
+ %w[animals cities people posts].each do |table|
42
+ DB.create_table(table) do
43
+ primary_key :id, :type => Integer
44
+ string :name
45
+ string :note
46
+ end
47
+ end
48
+
49
+ class Animal < Sequel::Model; end
50
+ class Cat < Animal; end
51
+ class City < Sequel::Model; end
52
+ class Post < Sequel::Model; end
53
+ class Person < Sequel::Model
54
+ def normalize_friendly_id(string)
55
+ string.upcase
56
+ end
57
+ end
58
+
59
+ [Cat, City, Post, Person].each do |klass|
60
+ klass.plugin :friendly_id, :name, :use_slug => true
61
+ end
62
+
63
+ # DB.loggers << Logger.new($stdout)
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: friendly_id_sequel
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 3
7
+ - 0
8
+ - 0
9
+ version: 3.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Norman Clarke
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-29 00:00:00 -03:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: friendly_id
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 3
29
+ - 0
30
+ - 0
31
+ - beta3
32
+ version: 3.0.0.beta3
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: sequel
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 3
44
+ - 8
45
+ - 0
46
+ version: 3.8.0
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ description: An adapter for using Sequel::Model with FriendlyId.
50
+ email: norman@njclarke.com
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ files:
58
+ - lib/friendly_id/sequel_adapter/create_slugs.rb
59
+ - lib/friendly_id/sequel_adapter/simple_model.rb
60
+ - lib/friendly_id/sequel_adapter/slug.rb
61
+ - lib/friendly_id/sequel_adapter/slugged_model.rb
62
+ - lib/friendly_id/sequel_adapter/version.rb
63
+ - lib/friendly_id_sequel.rb
64
+ - README.md
65
+ - LICENSE
66
+ - Rakefile
67
+ - test/basic_simple_test.rb
68
+ - test/basic_slugged_test.rb
69
+ - test/core.rb
70
+ - test/custom_normalizer_test.rb
71
+ - test/simple.rb
72
+ - test/slugged.rb
73
+ - test/sti_test.rb
74
+ - test/test_helper.rb
75
+ has_rdoc: true
76
+ homepage: http://norman.github.com/friendly_id_sequel
77
+ licenses: []
78
+
79
+ post_install_message:
80
+ rdoc_options: []
81
+
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project: friendly_id_sequel
101
+ rubygems_version: 1.3.6
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: A Sequel adapter for FriendlyId
105
+ test_files:
106
+ - test/basic_simple_test.rb
107
+ - test/basic_slugged_test.rb
108
+ - test/custom_normalizer_test.rb
109
+ - test/sti_test.rb