friendly_id4 4.0.0.beta6 → 4.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,31 +0,0 @@
1
- # encoding: utf-8
2
- $:.push File.expand_path("../lib", __FILE__)
3
-
4
- require "friendly_id"
5
-
6
- Gem::Specification.new do |s|
7
- s.name = "friendly_id4"
8
- s.version = FriendlyId::VERSION
9
- s.authors = ["Norman Clarke"]
10
- s.email = ["norman@njclarke.com"]
11
- s.homepage = "http://norman.github.com/friendly_id"
12
- s.summary = "A comprehensive slugging and pretty-URL plugin."
13
- s.rubyforge_project = "friendly_id"
14
- s.files = `git ls-files`.split("\n")
15
- s.test_files = `git ls-files -- {test}/*`.split("\n")
16
- s.require_paths = ["lib"]
17
-
18
- s.add_development_dependency "activerecord", "~> 3.0"
19
- s.add_development_dependency "sqlite3", "~> 1.3"
20
- s.add_development_dependency "cutest", "~> 1.1.2"
21
- s.add_development_dependency "ffaker"
22
- s.add_development_dependency "maruku"
23
- s.add_development_dependency "yard"
24
- s.add_development_dependency "mocha"
25
-
26
- s.description = <<-EOM
27
- FriendlyId is the "Swiss Army bulldozer" of slugging and permalink plugins
28
- for Ruby on Rails. It allows you to create pretty URL's and work with
29
- human-friendly strings as if they were numeric ids for ActiveRecord models.
30
- EOM
31
- end
@@ -1,134 +0,0 @@
1
- module FriendlyId
2
- # Class methods that will be added to model classes that extend {FriendlyId}.
3
- module Base
4
-
5
- # Configure FriendlyId's behavior in a model.
6
- #
7
- # class Post < ActiveRecord::Base
8
- # extend FriendlyId
9
- # friendly_id :title, :use => :slugged
10
- # end
11
- #
12
- # When given the optional block, this method will yield the class's instance
13
- # of {FriendlyId::Configuration} to the block before evaluating other
14
- # arguments, so configuration values set in the block may be overwritten by
15
- # the arguments. This order was chosen to allow passing the same proc to
16
- # multiple models, while being able to override the values it sets. Here is
17
- # a contrived example:
18
- #
19
- # $friendly_id_config_proc = Proc.new do |config|
20
- # config.base = :name
21
- # config.use :slugged
22
- # end
23
- #
24
- # class Foo < ActiveRecord::Base
25
- # extend FriendlyId
26
- # friendly_id &$friendly_id_config_proc
27
- # end
28
- #
29
- # class Bar < ActiveRecord::Base
30
- # extend FriendlyId
31
- # friendly_id :title, &$friendly_id_config_proc
32
- # end
33
- #
34
- # However, it's usually better to use {FriendlyId.defaults} for this:
35
- #
36
- # FriendlyId.defaults do |config|
37
- # config.base = :name
38
- # config.use :slugged
39
- # end
40
- #
41
- # class Foo < ActiveRecord::Base
42
- # extend FriendlyId
43
- # end
44
- #
45
- # class Bar < ActiveRecord::Base
46
- # extend FriendlyId
47
- # friendly_id :title
48
- # end
49
- #
50
- # In general you should use the block syntax either because of your personal
51
- # aesthetic preference, or because you need to share some functionality
52
- # between multiple models that can't be well encapsulated by
53
- # {FriendlyId.defaults}.
54
- #
55
- # === Order Method Calls in a Block vs Ordering Options
56
- #
57
- # When calling this method without a block, you may set the hash options in
58
- # any order.
59
- #
60
- # However, when using block-style invocation, be sure to call
61
- # FriendlyId::Configuration's {FriendlyId::Configuration#use use} method
62
- # *prior* to the associated configuration options, because it will include
63
- # modules into your class, and these modules in turn may add required
64
- # configuration options to the +@friendly_id_configuraton+'s class:
65
- #
66
- # class Person < ActiveRecord::Base
67
- # friendly_id do |config|
68
- # # This will work
69
- # config.use :slugged
70
- # config.sequence_separator = ":"
71
- # end
72
- # end
73
- #
74
- # class Person < ActiveRecord::Base
75
- # friendly_id do |config|
76
- # # This will fail
77
- # config.sequence_separator = ":"
78
- # config.use :slugged
79
- # end
80
- # end
81
- #
82
- # @option options [Symbol] :use The name of an addon to use. By default,
83
- # FriendlyId provides {FriendlyId::Slugged :slugged},
84
- # {FriendlyId::History :history}, {FriendlyId::Reserved :reserved}, and
85
- # {FriendlyId::Scoped :scoped}.
86
- #
87
- # @option options [Array] :reserved_words Available when using +:reserved+,
88
- # which is loaded by default. Sets an array of words banned for use as
89
- # the basis of a friendly_id. By default this includes "edit" and "new".
90
- #
91
- # @option options [Symbol] :scope Available when using +:scoped+.
92
- # Sets the relation or column used to scope generated friendly ids. This
93
- # option has no default value.
94
- #
95
- # @option options [Symbol] :sequence_separator Available when using +:slugged+.
96
- # Configures the sequence of characters used to separate a slug from a
97
- # sequence. Defaults to +--+.
98
- #
99
- # @option options [Symbol] :slug_column Available when using +:slugged+.
100
- # Configures the name of the column where FriendlyId will store the slug.
101
- # Defaults to +:slug+.
102
- #
103
- # @option options [Symbol] :slug_sequencer_class Available when using +:slugged+.
104
- # Sets the class used to generate unique slugs. You should not specify this
105
- # unless you're doing some extensive hacking on FriendlyId. Defaults to
106
- # {FriendlyId::SlugSequencer}.
107
- #
108
- # @yield Provides access to the model class's friendly_id_config, which
109
- # allows an alternate configuration syntax, and conditional configuration
110
- # logic.
111
- #
112
- # @yieldparam config The model class's {FriendlyId::Configuration friendly_id_config}.
113
- def friendly_id(base = nil, options = {}, &block)
114
- yield @friendly_id_config if block_given?
115
- @friendly_id_config.use options.delete :use
116
- @friendly_id_config.send :set, base ? options.merge(:base => base) : options
117
- before_save do |record|
118
- record.instance_eval {@current_friendly_id = friendly_id}
119
- end
120
- include Model
121
- end
122
-
123
- # Returns the model class's {FriendlyId::Configuration friendly_id_config}.
124
- # @note In the case of Single Table Inheritance (STI), this method will
125
- # duplicate the parent class's FriendlyId::Configuration instance on first
126
- # access. If you're concerned about thread safety, then be sure to invoke
127
- # {#friendly_id} in your class for each model.
128
- def friendly_id_config
129
- @friendly_id_config or begin
130
- @friendly_id_config = base_class.friendly_id_config.dup
131
- end
132
- end
133
- end
134
- end
@@ -1,78 +0,0 @@
1
- module FriendlyId
2
- # The configuration paramters passed to +friendly_id+ will be stored in
3
- # this object.
4
- class Configuration
5
-
6
- # The base column or method used by FriendlyId as the basis of a friendly id
7
- # or slug.
8
- #
9
- # For models that don't use FriendlyId::Slugged, the base is the column that
10
- # is used as the FriendlyId directly. For models using FriendlyId::Slugged,
11
- # the base is a column or method whose value is used as the basis of the
12
- # slug.
13
- #
14
- # For example, if you have a model representing blog posts and that uses
15
- # slugs, you likely will want to use the "title" attribute as the base, and
16
- # FriendlyId will take care of transforming the human-readable title into
17
- # something suitable for use in a URL.
18
- #
19
- # @param [Symbol] A symbol referencing a column or method in the model. This
20
- # value is usually set by passing it as the first argument to
21
- # {FriendlyId::Base#friendly_id friendly_id}:
22
- #
23
- # @example
24
- # class Book < ActiveRecord::Base
25
- # extend FriendlyId
26
- # friendly_id :name
27
- # end
28
- attr_accessor :base
29
-
30
- # The default configuration options.
31
- attr_reader :defaults
32
-
33
- # The model class that this configuration belongs to.
34
- # @return ActiveRecord::Base
35
- attr_reader :model_class
36
-
37
- def initialize(model_class, values = nil)
38
- @model_class = model_class
39
- @defaults = {}
40
- set values
41
- end
42
-
43
- # Lets you specify the modules to use with FriendlyId.
44
- #
45
- # This method is invoked by {FriendlyId::Base#friendly_id friendly_id} when
46
- # passing the +:use+ option, or when using {FriendlyId::Base#friendly_id
47
- # friendly_id} with a block.
48
- #
49
- # @example
50
- # class Book < ActiveRecord::Base
51
- # extend FriendlyId
52
- # friendly_id :name, :use => :slugged
53
- # end
54
- # @param [#to_s] *modules Arguments should be a symbols or strings that
55
- # correspond with the name of a module inside the FriendlyId namespace. By
56
- # default FriendlyId provides +:slugged+, +:history+ and +:scoped+.
57
- def use(*modules)
58
- modules.to_a.flatten.compact.map do |name|
59
- model_class.send :include, FriendlyId.const_get(name.to_s.classify)
60
- end
61
- end
62
-
63
- # The column that FriendlyId will use to find the record when querying by
64
- # friendly id.
65
- #
66
- # This method is generally only used internally by FriendlyId.
67
- # @return String
68
- def query_field
69
- base.to_s
70
- end
71
-
72
- private
73
-
74
- def set(values)
75
- values and values.each {|name, value| self.send "#{name}=", value}
76
- end
77
- end
78
- end
@@ -1,20 +0,0 @@
1
- module FriendlyId
2
- # These methods will override the finder methods in ActiveRecord::Relation.
3
- module FinderMethods
4
-
5
- protected
6
-
7
- # FriendlyId overrides this method to make it possible to use friendly id's
8
- # identically to numeric ids in finders.
9
- #
10
- # @example
11
- # person = Person.find(123)
12
- # person = Person.find("joe")
13
- #
14
- # @see FriendlyId::ObjectUtils
15
- def find_one(id)
16
- return super if !@klass.respond_to?(:friendly_id) || id.unfriendly_id?
17
- where(@klass.friendly_id_config.query_field => id).first or super
18
- end
19
- end
20
- end
@@ -1,64 +0,0 @@
1
- require "friendly_id/slug"
2
-
3
- module FriendlyId
4
-
5
- =begin
6
- FriendlyId can maintain a history of your record's older slugs, so if your
7
- record's friendly_id changes, your URL's won't break.
8
-
9
- class Post < ActiveRecord::Base
10
- extend FriendlyId
11
- friendly_id :title, :use => :history
12
- end
13
-
14
- class PostsController < ApplicationController
15
-
16
- before_filter :find_post
17
-
18
- ...
19
- def find_post
20
- return unless params[:id]
21
- @post = begin
22
- Post.find params[:id]
23
- rescue ActiveRecord::RecordNotFound
24
- Post.find_by_friendly_id params[:id]
25
- end
26
- # If an old id or a numeric id was used to find the record, then
27
- # the request path will not match the post_path, and we should do
28
- # a 301 redirect that uses the current friendly_id
29
- if request.path != post_path(@post)
30
- return redirect_to @post, :status => :moved_permanently
31
- end
32
- end
33
- end
34
- =end
35
- module History
36
-
37
- # Configures the model instance to use the History add-on.
38
- def self.included(klass)
39
- klass.instance_eval do
40
- raise "FriendlyId::History is incompatibe with FriendlyId::Scoped" if self < Scoped
41
- include Slugged unless self < Slugged
42
- has_many :friendly_id_slugs, :as => :sluggable, :dependent => :destroy
43
- before_save :build_friendly_id_slug, :if => lambda {|r| r.slug_sequencer.slug_changed?}
44
- scope :with_friendly_id, lambda {|id| includes(:friendly_id_slugs).where("friendly_id_slugs.slug = ?", id)}
45
- extend Finder
46
- end
47
- end
48
-
49
- private
50
-
51
- def build_friendly_id_slug
52
- self.friendly_id_slugs.build :slug => friendly_id
53
- end
54
- end
55
-
56
- # Adds a finder that explictly uses slugs from the slug table.
57
- module Finder
58
-
59
- # Search for a record in the slugs table using the specified slug.
60
- def find_by_friendly_id(*args)
61
- with_friendly_id(args.shift).first(*args)
62
- end
63
- end
64
- end
@@ -1,18 +0,0 @@
1
- class CreateFriendlyIdSlugs < ActiveRecord::Migration
2
-
3
- def self.up
4
- create_table :friendly_id_slugs do |t|
5
- t.string :slug, :null => false
6
- t.integer :sluggable_id, :null => false
7
- t.string :sluggable_type, :limit => 40
8
- t.datetime :created_at
9
- end
10
- add_index :friendly_id_slugs, :sluggable_id
11
- add_index :friendly_id_slugs, [:slug, :sluggable_type], :unique => true
12
- add_index :friendly_id_slugs, :sluggable_type
13
- end
14
-
15
- def self.down
16
- drop_table :friendly_id_slugs
17
- end
18
- end
@@ -1,22 +0,0 @@
1
- module FriendlyId
2
- # Instance methods that will be added to all classes using FriendlyId.
3
- module Model
4
-
5
- attr_reader :current_friendly_id
6
-
7
- # Convenience method for accessing the class method of the same name.
8
- def friendly_id_config
9
- self.class.friendly_id_config
10
- end
11
-
12
- # Get the instance's friendly_id.
13
- def friendly_id
14
- send friendly_id_config.query_field
15
- end
16
-
17
- # Either the friendly_id, or the numeric id cast to a string.
18
- def to_param
19
- (friendly_id.present? ? friendly_id : id).to_s
20
- end
21
- end
22
- end
@@ -1,40 +0,0 @@
1
- module FriendlyId
2
- # Utility methods for determining whether any object is a friendly id.
3
- #
4
- # Monkey-patching Object is a somewhat extreme measure not to be taken lightly
5
- # by libraries, but in this case I decided to do it because to me, it feels
6
- # cleaner than adding a module method to {FriendlyId}. I've given the methods
7
- # names that unambigously refer to the library of their origin, which should
8
- # be sufficient to avoid conflicts with other libraries.
9
- module ObjectUtils
10
-
11
- # True is the id is definitely friendly, false if definitely unfriendly,
12
- # else nil.
13
- #
14
- # An object is considired "definitely unfriendly" if its class is or
15
- # inherits from Numeric, Symbol or ActiveRecord::Base.
16
- #
17
- # An object is considered "definitely friendly" if it responds to +to_i+,
18
- # and its value when cast to an integer and then back to a string is
19
- # different from its value when merely cast to a string:
20
- #
21
- # 123.friendly_id? #=> false
22
- # "123".friendly_id? #=> nil
23
- # "abc123".friendly_id? #=> true
24
- def friendly_id?
25
- if [Numeric, Symbol, ActiveRecord::Base].detect {|klass| self.class < klass}
26
- false
27
- elsif respond_to?(:to_i) && to_i.to_s != to_s
28
- true
29
- end
30
- end
31
-
32
- # True if the id is definitely unfriendly, false if definitely friendly,
33
- # else nil.
34
- def unfriendly_id?
35
- val = friendly_id? ; !val unless val.nil?
36
- end
37
- end
38
- end
39
-
40
- Object.send :include, FriendlyId::ObjectUtils
@@ -1,46 +0,0 @@
1
- module FriendlyId
2
-
3
- =begin
4
- This module adds the ability to exlude a list of words from use as
5
- FriendlyId slugs.
6
-
7
- By default, FriendlyId reserves the words "new" and "edit" when this module
8
- is included. You can configure this globally by using {FriendlyId.defaults FriendlyId.defaults}:
9
-
10
- FriendlyId.defaults do |config|
11
- config.use :reserved
12
- # Reserve words for English and Spanish URLs
13
- config.reserved_words = %w(new edit nueva nuevo editar)
14
- end
15
- =end
16
- module Reserved
17
-
18
- # When included, this module adds configuration options to the model class's
19
- # friendly_id_config.
20
- def self.included(model_class)
21
- model_class.class_eval do
22
- friendly_id_config.class.send :include, Reserved::Configuration
23
- friendly_id_config.defaults[:reserved_words] ||= ["new", "edit"]
24
- end
25
- end
26
-
27
- # This module adds the +:reserved_words+ configuration option to
28
- # {FriendlyId::Configuration FriendlyId::Configuration}.
29
- module Configuration
30
- attr_writer :reserved_words
31
-
32
- # Overrides {FriendlyId::Configuration#base} to add a validation to the
33
- # model class.
34
- def base=(base)
35
- super
36
- reserved_words = model_class.friendly_id_config.reserved_words
37
- model_class.validates_exclusion_of base, :in => reserved_words
38
- end
39
-
40
- # An array of words forbidden as slugs.
41
- def reserved_words
42
- @reserved_words ||= @defaults[:reserved_words]
43
- end
44
- end
45
- end
46
- end