ismasan-sluggable_finder 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-11-03
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,16 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.markdown
5
+ Rakefile
6
+ lib/sluggable_finder.rb
7
+ lib/sluggable_finder/finder.rb
8
+ lib/sluggable_finder/orm.rb
9
+ script/console
10
+ script/destroy
11
+ script/generate
12
+ spec/sluggable_finder_spec.rb
13
+ spec/spec.opts
14
+ spec/spec_helper.rb
15
+ tasks/rspec.rake
16
+ tasks/db.rake
data/PostInstall.txt ADDED
@@ -0,0 +1,4 @@
1
+
2
+ For more information on sluggable_finder, see http://github.com/ismasan/sluggable-finder or the README file
3
+
4
+ If you want to contribute don't forget to add your specs!
data/README.markdown ADDED
@@ -0,0 +1,117 @@
1
+ ## sluggable_finder
2
+
3
+ Ismael Celis
4
+
5
+ http://github.com/ismasan/sluggable_finder
6
+
7
+ ## DESCRIPTION:
8
+
9
+ This is a variation of acts_as_sluggable, permalink_fu and acts_as_permalink.
10
+ This plugin allows models to generate a unique "slug" (url-enabled name) from any regular attribute.
11
+ Sluggable models can have a scope parameter so slugs are unique relative to a parent model.
12
+
13
+ The plugin intercepts ActiveRecord::Base.find to look into the slug field if passed a single string as an argument. It works as normal if you pass an integer or more finder parameters.
14
+
15
+ The plugin modifies to_param so it's transparent to link_to and url_for view helpers
16
+
17
+ ## FEATURES/PROBLEMS:
18
+
19
+ Slugs are created when a model is created. Subsequent changes to the source field will not modify the slug unless you specifically change the value of the slug field. This is because permalinks should never change.
20
+
21
+ Complete specs. To test, make sure you create an empty SQLite database file in spec/db/test.db
22
+
23
+ Then run the following to load the test schema:
24
+
25
+ rake db:create
26
+
27
+ ## SYNOPSIS:
28
+
29
+ ### Models
30
+ class Category < ActiveRecord::Base
31
+ has_many :posts
32
+ sluggable_finder :title #slugifies the :title field into the :slug field
33
+ end
34
+
35
+ class Post < ActiveRecord::Base
36
+ belongs_to :category
37
+ has_many :comments
38
+ sluggable_finder :title, :scope => :category_id #Post slugs are unique to the parent category
39
+ end
40
+
41
+ class Comment < ActiveRecord::Base
42
+ belongs_to :post
43
+ sluggable_finder :get_slug, :to => :permalink #creates slug from custom attribute and stores it in "permalink" field
44
+
45
+ def get_slug #we define the custom attribute
46
+ "#{post.id}-#{Time.now}"
47
+ end
48
+ end
49
+
50
+ # Provide a list or reserved slugs you don't want available as permalinks
51
+ #
52
+ sluggable_finder :title, :reserved_slugs => %w(admin settings users)
53
+
54
+ ### Controllers
55
+
56
+ You can do Model.find(slug) just how you would with a single numerical ID. It will also raise a RecordNotFound exception so you can handle that in your application controller.
57
+ The idea is that you keep your controller actions clean and handle Not Found errors elsewhere. You can still use Model.find the regular way.
58
+
59
+ class PostsController < ApplicationController
60
+ # params[:id] is a string, URL-encoded slug
61
+ def show
62
+ @post = Post.find( params[:id] ) #raises ActiveRecord::RecordNotFound if not found
63
+ end
64
+ end
65
+
66
+ ### Links
67
+
68
+ Link generation remains the same, because the plugin overwrites your model's to_param method
69
+
70
+ <%= link_to h(@post.title), @post %> # => <a href="/posts/hello-world">Hello world</a>
71
+
72
+ ## REQUIREMENTS:
73
+
74
+ ActiveRecord, ActiveSupport
75
+
76
+ ## INSTALL:
77
+
78
+ At the moment this is not available in Github's gem repository, so you'll need to install manually:
79
+
80
+ git clone git://github.com/ismasan/sluggable-finder.git
81
+ cd sluggable_finder
82
+ gem build sluggable_finder.gemspec
83
+ sudo gem install sluggable_finder.gem
84
+
85
+
86
+ Then, in your Rails app's environment:
87
+
88
+ config.gem 'sluggable_finder'
89
+
90
+ If you wan to unpack the gem to you app's "vendor" directory:
91
+
92
+ rake gems:unpack
93
+
94
+ ## LICENSE:
95
+
96
+ (The MIT License)
97
+
98
+ Copyright (c) 2008 Ismael Celis
99
+
100
+ Permission is hereby granted, free of charge, to any person obtaining
101
+ a copy of this software and associated documentation files (the
102
+ 'Software'), to deal in the Software without restriction, including
103
+ without limitation the rights to use, copy, modify, merge, publish,
104
+ distribute, sublicense, and/or sell copies of the Software, and to
105
+ permit persons to whom the Software is furnished to do so, subject to
106
+ the following conditions:
107
+
108
+ The above copyright notice and this permission notice shall be
109
+ included in all copies or substantial portions of the Software.
110
+
111
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
112
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
113
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
114
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
115
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
116
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
117
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/sluggable_finder'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('sluggable_finder', SluggableFinder::VERSION) do |p|
7
+ p.developer('Ismael Celis', 'ismaelct@gmail.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
10
+ p.rubyforge_name = p.name # TODO this is default value
11
+ # p.extra_deps = [
12
+ # ['activesupport','>= 2.0.2'],
13
+ # ]
14
+ p.extra_dev_deps = [
15
+ ['newgem', ">= #{::Newgem::VERSION}"]
16
+ ]
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
26
+
27
+ # TODO - want other tests/tasks run by default? Add them to the list
28
+ # task :default => [:spec, :features]
@@ -0,0 +1,42 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module SluggableFinder
5
+ VERSION = '2.0.0'
6
+
7
+ class << self
8
+
9
+ def enable_activerecord
10
+ ActiveRecord::Base.extend SluggableFinder::Finder
11
+ ActiveRecord::Base.class_eval{include SluggableFinder::Orm}
12
+ # support for associations
13
+ a = ActiveRecord::Associations
14
+ returning([ a::AssociationCollection ]) { |classes|
15
+ # detect http://dev.rubyonrails.org/changeset/9230
16
+ unless a::HasManyThroughAssociation.superclass == a::HasManyAssociation
17
+ classes << a::HasManyThroughAssociation
18
+ end
19
+ }.each do |klass|
20
+ klass.send :include, SluggableFinder::Finder
21
+ klass.class_eval { alias_method_chain :find, :slug }
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ def self.encode(str)
29
+ ActiveSupport::Multibyte::Handlers::UTF8Handler.
30
+ normalize(str,:d).split(//u).reject { |e| e.length > 1 }.join.strip.gsub(/[^a-z0-9]+/i, '-').downcase
31
+ end
32
+
33
+ end
34
+
35
+ require 'rubygems'
36
+ require 'active_record'
37
+
38
+ Dir.glob('lib/sluggable_finder/*.rb').each do |file|
39
+ require file
40
+ end
41
+
42
+ SluggableFinder.enable_activerecord if (defined?(ActiveRecord) && !ActiveRecord::Base.respond_to?(:sluggable_finder))
@@ -0,0 +1,17 @@
1
+ module SluggableFinder
2
+ # This module is included by the base class as well as AR asociation collections
3
+ #
4
+ module Finder
5
+
6
+ def find_with_slug(*args)
7
+ if (args.first.is_a?(String) and !(args.first =~ /\A\d+\Z/))#only contain digits
8
+ options = {:conditions => ["#{ sluggable_finder_options[:to]} = ?", args.first]}
9
+ first(options) or
10
+ raise ActiveRecord::RecordNotFound.new("There is no #{sluggable_finder_options[:sluggable_type]} with #{sluggable_finder_options[:to]} '#{args.first}'")
11
+ else
12
+ find_without_slug(*args)
13
+ end
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,111 @@
1
+ module SluggableFinder
2
+ module Orm
3
+
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ base.class_eval{include InstanceMethods}
7
+ class << base
8
+ alias_method_chain :find, :slug
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+
14
+ def sluggable_finder(field = :title, options = {})
15
+ write_inheritable_attribute(:sluggable_finder_options, {
16
+ :sluggable_type => ActiveRecord::Base.send(:class_name_of_active_record_descendant, self).to_s,
17
+ :from => field,
18
+ :scope => nil,
19
+ :to => :slug,
20
+ :reserved_slugs => []
21
+ }.merge( options ))
22
+ class_inheritable_reader :sluggable_finder_options
23
+
24
+ if sluggable_finder_options[:scope]
25
+ scope_condition_method = %(
26
+ def scope_condition
27
+ "#{sluggable_finder_options[:scope].to_s} = \#{#{sluggable_finder_options[:scope].to_s}}"
28
+ end
29
+ )
30
+ else
31
+ scope_condition_method = %(
32
+ def scope_condition
33
+ '1 = 1'
34
+ end
35
+ )
36
+ end
37
+
38
+ class_eval <<-EOV
39
+
40
+ def slugable_class
41
+ ::#{self.name}
42
+ end
43
+
44
+ def source_column
45
+ "#{sluggable_finder_options[:from]}"
46
+ end
47
+
48
+ def destination_column
49
+ "#{sluggable_finder_options[:to]}"
50
+ end
51
+
52
+ def the_scope
53
+ "#{sluggable_finder_options[:scope]}"
54
+ end
55
+
56
+ def to_param
57
+ send("#{sluggable_finder_options[:to]}")
58
+ end
59
+
60
+ #{scope_condition_method}
61
+
62
+ after_validation :set_slug
63
+ EOV
64
+
65
+ end
66
+
67
+ end
68
+
69
+ module InstanceMethods
70
+
71
+
72
+ def set_slug
73
+ s = self.create_sluggable_slug
74
+ write_attribute(destination_column, s)
75
+ end
76
+
77
+ def create_sluggable_slug
78
+ suffix = ''
79
+ begin
80
+ proposed_slug = if self.send(destination_column.to_sym).blank?
81
+ SluggableFinder.encode self.send(source_column.to_sym)
82
+ else
83
+ SluggableFinder.encode self.send(destination_column.to_sym)
84
+ end
85
+ rescue Exception => e
86
+ raise e
87
+ end
88
+ cond = if new_record?
89
+ ''
90
+ else
91
+ "id != #{id} AND "
92
+ end
93
+ slugable_class.transaction do
94
+ #case insensitive
95
+ existing = slugable_class.find(:first, :conditions => ["#{cond}#{destination_column} LIKE ? and #{scope_condition}", proposed_slug + suffix])
96
+ while existing != nil or sluggable_finder_options[:reserved_slugs].include?(proposed_slug + suffix)
97
+ if suffix.empty?
98
+ suffix = "-2"
99
+ else
100
+ suffix.succ!
101
+ end
102
+ existing = slugable_class.find(:first, :conditions => ["#{cond}#{destination_column} = ? and #{scope_condition}", proposed_slug + suffix])
103
+ end
104
+ end # end of transaction
105
+ proposed_slug + suffix
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+ end
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/sluggable_finder.rb'}"
9
+ puts "Loading sluggable_finder gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,194 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ ActiveRecord::Base.establish_connection(
4
+ :adapter=>'sqlite3',
5
+ :dbfile=> File.join(File.dirname(__FILE__),'db','test.db')
6
+ )
7
+
8
+ LOGGER = Logger.new(File.dirname(__FILE__)+'/log/test.log')
9
+ ActiveRecord::Base.logger = LOGGER
10
+
11
+ # A test Model according to test schema in db/test.db
12
+ #
13
+ class Item < ActiveRecord::Base
14
+ named_scope :published, :conditions => {:published => true}
15
+ end
16
+
17
+ # Simple slug
18
+ #
19
+ class SimpleItem < Item
20
+ sluggable_finder :title, :reserved_slugs => ['admin','settings'] # defaults :to => :slug
21
+ end
22
+
23
+ # Slug from virtual attribute
24
+ #
25
+ class VirtualItem < Item
26
+ sluggable_finder :some_method
27
+
28
+ def some_method
29
+ "#{self.class.name} #{title}"
30
+ end
31
+
32
+ end
33
+
34
+ # This one saves slug into 'permalink' field
35
+ #
36
+ class PermalinkItem < Item
37
+ sluggable_finder :title, :to => :permalink
38
+ end
39
+
40
+ # A top level object to test scoped slugs
41
+ #
42
+ class Category < ActiveRecord::Base
43
+ has_many :scoped_items
44
+ end
45
+
46
+ class ScopedItem < Item
47
+ belongs_to :category
48
+ sluggable_finder :title, :scope => :category_id
49
+ end
50
+
51
+ describe SimpleItem, 'encoding permalinks' do
52
+ before(:each) do
53
+ Item.delete_all
54
+ @item = SimpleItem.create!(:title => 'Hello World')
55
+ @item2 = SimpleItem.create(:title => 'Hello World')
56
+ @item3 = SimpleItem.create(:title => 'Admin')
57
+ end
58
+
59
+ it "should connect to test sqlite db" do
60
+ Item.count.should == 3
61
+ end
62
+
63
+ it "should create unique slugs" do
64
+ @item.slug.should == 'hello-world'
65
+ @item2.slug.should == 'hello-world-2'
66
+ end
67
+
68
+ it "should define to_param to return slug" do
69
+ @item.to_param.should == 'hello-world'
70
+ end
71
+
72
+ it "should raise ActiveRecord::RecordNotFound" do
73
+ SimpleItem.create!(:title => 'Hello World')
74
+ lambda {
75
+ SimpleItem.find 'non-existing-slug'
76
+ }.should raise_error(ActiveRecord::RecordNotFound)
77
+ end
78
+
79
+ it "should find normally by ID" do
80
+ SimpleItem.find(@item.id).should == @item
81
+ end
82
+
83
+ it "should by ID even if ID is string" do
84
+ SimpleItem.find(@item.id.to_s).should == @item
85
+ end
86
+
87
+ it "should not create reserved slug" do
88
+ lambda {
89
+ SimpleItem.find 'admin'
90
+ }.should raise_error(ActiveRecord::RecordNotFound)
91
+ SimpleItem.find('admin-2').to_param.should == @item3.to_param
92
+ end
93
+
94
+ it "should keep original slugs" do
95
+ @item.title = 'some other title'
96
+ @item.save
97
+ @item.to_param.should == 'hello-world'
98
+ end
99
+ end
100
+
101
+ describe SimpleItem, "with non-english characters" do
102
+ before(:each) do
103
+ @item = SimpleItem.create!(:title => "Un ñandú super ñoño I've seen")
104
+ end
105
+
106
+ it "should turn them to english characters" do
107
+ @item.to_param.should == "un-nandu-super-nono-i-ve-seen"
108
+ end
109
+ end
110
+
111
+ describe VirtualItem, 'using virtual fields as permalink source' do
112
+ before(:each) do
113
+ Item.delete_all
114
+ @item = VirtualItem.create!(:title => 'prefixed title')
115
+ end
116
+
117
+ it "should generate slug from a virtual attribute" do
118
+ @item.to_param.should == 'virtualitem-prefixed-title'
119
+ end
120
+
121
+ it "should find by slug" do
122
+ VirtualItem.find('virtualitem-prefixed-title').to_param.should == @item.to_param
123
+ end
124
+ end
125
+
126
+ describe PermalinkItem,'writing to custom field' do
127
+ before(:each) do
128
+ Item.delete_all
129
+ @item = PermalinkItem.create! :title => 'Hello World'
130
+ end
131
+
132
+ it "should create slug in custom field if provided" do
133
+
134
+ @item.permalink.should == 'hello-world'
135
+ @item.slug.should == nil
136
+ end
137
+ end
138
+
139
+ describe ScopedItem,'scoped to parent object' do
140
+ before(:each) do
141
+ Item.delete_all
142
+ @category1 = Category.create!(:name => 'Category one')
143
+ @category2 = Category.create!(:name => 'Category two')
144
+ # Lets create 3 items with the same title, two of them in the same category
145
+ @item1 = @category1.scoped_items.create!(:title => 'A scoped item',:published => true)
146
+ @item2 = @category1.scoped_items.create!(:title => 'A scoped item', :published => false)
147
+ @item3 = @category2.scoped_items.create!(:title => 'A scoped item')
148
+ end
149
+
150
+ it "should scope slugs to parent items" do
151
+ @item1.to_param.should == 'a-scoped-item'
152
+ @item2.to_param.should == 'a-scoped-item-2' # because this slug is not available for this category
153
+ @item3.to_param.should == 'a-scoped-item'
154
+ end
155
+
156
+ it "should include sluggable methods in collections" do
157
+ @category1.scoped_items.respond_to?(:find_with_slug).should == true
158
+ end
159
+
160
+ it "should find by scoped slug" do
161
+ item1 = @category1.scoped_items.find('a-scoped-item')
162
+ item1.to_param.should == @item1.to_param
163
+ end
164
+
165
+ it "should find published one (named scope)" do
166
+ @category1.scoped_items.published.find('a-scoped-item').to_param.should == @item1.to_param
167
+ end
168
+
169
+ it "should not find unpublished one (named scope)" do
170
+ lambda{
171
+ @category1.scoped_items.published.find('a-scoped-item-2')
172
+ }.should raise_error(ActiveRecord::RecordNotFound)
173
+ end
174
+ end
175
+
176
+ describe SimpleItem, 'with AR named scopes' do
177
+ before(:each) do
178
+ Item.delete_all
179
+ @published_one = SimpleItem.create! :title => 'published 1',:published => true
180
+ @published_two = SimpleItem.create! :title => 'published 2',:published => true
181
+ @unpublished = SimpleItem.create! :title => 'not published',:published => false
182
+ end
183
+
184
+ it "should find published ones" do
185
+ SimpleItem.published.find('published-1').to_param.should == @published_one.to_param
186
+ SimpleItem.published.find('published-2').to_param.should == @published_two.to_param
187
+ end
188
+
189
+ it "should not find unpublished ones" do
190
+ lambda {
191
+ SimpleItem.published.find('not-published')
192
+ }.should raise_error(ActiveRecord::RecordNotFound)
193
+ end
194
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,10 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'sluggable_finder'
data/tasks/db.rake ADDED
@@ -0,0 +1,35 @@
1
+ ActiveRecord::Base.establish_connection(
2
+ :adapter=>'sqlite3',
3
+ :dbfile=> File.join(File.dirname(__FILE__),'..','spec','db','test.db')
4
+ )
5
+ # define a migration
6
+ class TestSchema < ActiveRecord::Migration
7
+ def self.up
8
+ create_table :items do |t|
9
+ t.string :title
10
+ t.string :slug
11
+ t.string :permalink
12
+ t.boolean :published
13
+ t.integer :category_id
14
+ t.timestamps
15
+ end
16
+ end
17
+
18
+ def self.down
19
+ drop_table :items
20
+ end
21
+ end
22
+
23
+
24
+ namespace :db do
25
+ desc "Create test schema"
26
+ task :create => :destroy do
27
+ # run the migration
28
+ TestSchema.migrate(:up)
29
+ end
30
+
31
+ desc "Destroy test schema"
32
+ task :destroy do
33
+ TestSchema.migrate(:down)
34
+ end
35
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ismasan-sluggable_finder
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ismael Celis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-11-04 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: newgem
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.0.5
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: hoe
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 1.8.0
32
+ version:
33
+ description:
34
+ email:
35
+ - ismaelct@gmail.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - History.txt
42
+ - Manifest.txt
43
+ - PostInstall.txt
44
+ - README.markdown
45
+ files:
46
+ - History.txt
47
+ - Manifest.txt
48
+ - PostInstall.txt
49
+ - README.markdown
50
+ - Rakefile
51
+ - lib/sluggable_finder.rb
52
+ - lib/sluggable_finder/finder.rb
53
+ - lib/sluggable_finder/orm.rb
54
+ - script/console
55
+ - script/destroy
56
+ - script/generate
57
+ - spec/sluggable_finder_spec.rb
58
+ - spec/spec.opts
59
+ - spec/spec_helper.rb
60
+ - tasks/rspec.rake
61
+ - tasks/db.rake
62
+ has_rdoc: false
63
+ homepage:
64
+ post_install_message: PostInstall.txt
65
+ rdoc_options:
66
+ - --main
67
+ - README.markdown
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project: sluggable_finder
85
+ rubygems_version: 1.2.0
86
+ signing_key:
87
+ specification_version: 2
88
+ summary: Automatically create SEO friendly, unique permalinks for your ActiveRecord objects. Behaves exactly as ActiveRecord#find
89
+ test_files: []
90
+