seofy 0.0.1

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.
@@ -0,0 +1,3 @@
1
+ .rvmrc
2
+ *.swp
3
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in seofy.gemspec
4
+ gemspec
@@ -0,0 +1,50 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ seofy (0.0.1)
5
+ activerecord (~> 3.0.0)
6
+ activesupport (~> 3.0.0)
7
+ babosa (~> 0.3.0)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activemodel (3.0.7)
13
+ activesupport (= 3.0.7)
14
+ builder (~> 2.1.2)
15
+ i18n (~> 0.5.0)
16
+ activerecord (3.0.7)
17
+ activemodel (= 3.0.7)
18
+ activesupport (= 3.0.7)
19
+ arel (~> 2.0.2)
20
+ tzinfo (~> 0.3.23)
21
+ activesupport (3.0.7)
22
+ arel (2.0.10)
23
+ babosa (0.3.4)
24
+ builder (2.1.2)
25
+ diff-lcs (1.1.2)
26
+ growl (1.0.3)
27
+ guard (0.3.4)
28
+ thor (~> 0.14.6)
29
+ i18n (0.5.0)
30
+ rspec (2.5.0)
31
+ rspec-core (~> 2.5.0)
32
+ rspec-expectations (~> 2.5.0)
33
+ rspec-mocks (~> 2.5.0)
34
+ rspec-core (2.5.2)
35
+ rspec-expectations (2.5.0)
36
+ diff-lcs (~> 1.1.2)
37
+ rspec-mocks (2.5.0)
38
+ sqlite3 (1.3.3)
39
+ thor (0.14.6)
40
+ tzinfo (0.3.27)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ growl
47
+ guard
48
+ rspec (~> 2.5.0)
49
+ seofy!
50
+ sqlite3
@@ -0,0 +1,5 @@
1
+ guard 'rspec', :version => 2, :cli => "--color --format nested --fail-fast" do
2
+ watch(%r{^spec/.+_spec\.rb})
3
+ watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
@@ -0,0 +1,40 @@
1
+ Seofy
2
+ ====
3
+
4
+ A simple plugin make permalink for you records.
5
+
6
+ Note: only supprt Rails 3
7
+
8
+
9
+ Installation
10
+ -----
11
+
12
+ gem install seofy
13
+
14
+ Rails 3
15
+
16
+ gem 'seofy'
17
+
18
+
19
+ Usage
20
+ -----
21
+
22
+ # existing_column adapter
23
+ class User < ActiveRecord::Base
24
+ seofy :source => :name, :adapter => :existing_column, :adapter_option => {:column => :slug}
25
+ end
26
+
27
+ # base36 adapter
28
+ class Store < ActiveRecord::Base
29
+ seofy :source => :title, :adapter => :base36, :adapter_option => {:length => 3, :column => :slug }
30
+ end
31
+
32
+ User.for_slug("SLUG")
33
+
34
+
35
+ Rake task
36
+ --------
37
+
38
+ rake seofy:update_all MODELS=User,Store
39
+
40
+ rake seofy:update_null MODELS=User,Store
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,14 @@
1
+ require 'babosa'
2
+ require 'seofy/active_record'
3
+ require 'seofy/configuration'
4
+ require 'seofy/task_runner'
5
+ require 'seofy/adapters/base'
6
+ require 'seofy/adapters/existing_column'
7
+ require 'seofy/adapters/base36'
8
+ require 'seofy/encoders/base36'
9
+
10
+ module Seofy
11
+ end
12
+
13
+ require "seofy/railtie" if defined?(Rails) && Rails.version >= "3"
14
+
@@ -0,0 +1,50 @@
1
+ module Seofy
2
+ module ActiveRecord
3
+ module ClassMethods
4
+ def seofy(options={})
5
+ init_seofy_config(options)
6
+ include ::Seofy::ActiveRecord::InstanceMethods
7
+ before_save :seofy_before_save
8
+ after_save :seofy_after_save
9
+ end
10
+
11
+ def init_seofy_config(options={})
12
+ class_attribute :seofy_config
13
+ self.seofy_config = ::Seofy::Configuration.new(options)
14
+ end
15
+
16
+ def seofy_adapter
17
+ self.seofy_config.adapter
18
+ end
19
+
20
+ def for_slug(param)
21
+ self.send("find_by_#{seofy_adapter.column}", param.split("-").last)
22
+ end
23
+ end
24
+
25
+ module InstanceMethods
26
+ def to_param
27
+ [seofy_source.to_s, seofy_slug].join("-").to_slug.normalize.to_s
28
+ end
29
+
30
+ def seofy_slug
31
+ self.class.seofy_adapter.seofy_slug(self)
32
+ end
33
+
34
+ def seofy_source
35
+ self.send(self.class.seofy_config.source).to_s
36
+ end
37
+
38
+ def seofy_before_save
39
+ self.class.seofy_adapter.before_save(self)
40
+ end
41
+
42
+ def seofy_after_save
43
+ self.class.seofy_adapter.after_save(self)
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+
50
+ ActiveRecord::Base.extend Seofy::ActiveRecord::ClassMethods
File without changes
@@ -0,0 +1,27 @@
1
+ module Seofy
2
+ module Adapters
3
+ class Base
4
+ attr_reader :options, :column
5
+ def initialize(options={})
6
+ @options = options
7
+ @column = options[:column]
8
+ end
9
+
10
+ def seofy_slug(inst)
11
+ raise "not implement"
12
+ end
13
+
14
+ def set_seofy_slug(inst)
15
+ raise "not implement"
16
+ end
17
+
18
+ def before_save(inst)
19
+ set_seofy_slug(inst)
20
+ end
21
+
22
+ def after_save(inst)
23
+ # do nothing
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ module Seofy
2
+ module Adapters
3
+ class Base36 < Base
4
+ attr_reader :options, :length, :column
5
+ def initialize(options={})
6
+ super(options)
7
+ @length = options[:length]
8
+ end
9
+
10
+ def seofy_slug(inst)
11
+ inst.send(self.column)
12
+ end
13
+
14
+ def set_seofy_slug(inst)
15
+ inst.send("#{column}=", ::Seofy::Encoders::Base36.random(self.length))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Seofy
2
+ module Adapters
3
+ class ExistingColumn < Base
4
+ attr_reader :column
5
+ def initialize(options={})
6
+ super(options)
7
+ end
8
+
9
+ def seofy_slug(inst)
10
+ inst.send(self.column)
11
+ end
12
+
13
+ def set_seofy_slug(inst)
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,11 @@
1
+ module Seofy
2
+ class Configuration
3
+ attr_reader :source, :adapter
4
+ def initialize(options)
5
+ @source = options[:source]
6
+ adapter_klass = "seofy/adapters/#{options[:adapter]}".camelize.constantize
7
+ @adapter = adapter_klass.new(options[:adapter_option])
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,41 @@
1
+ module Seofy
2
+ module Encoders
3
+ module Base36
4
+ THIRTY_SIX = ('0'..'9').to_a + ('a'..'z').to_a
5
+ LENGTH = THIRTY_SIX.size
6
+
7
+ def encode( numeric )
8
+ raise ArgumentError unless Numeric === numeric
9
+
10
+ return '0' if numeric == 0
11
+ s = ''
12
+
13
+ while numeric > 0
14
+ s << Base36::THIRTY_SIX[numeric.modulo(LENGTH)]
15
+ numeric /= LENGTH
16
+ end
17
+ s.reverse
18
+ end
19
+
20
+ def decode( base36 )
21
+ s = base36.to_s.reverse.split('')
22
+
23
+ total = 0
24
+ s.each_with_index do |char, index|
25
+ if ord = THIRTY_SIX.index(char)
26
+ total += ord * (LENGTH ** index)
27
+ else
28
+ raise ArgumentError, "#{base36} has #{char} which is not valid"
29
+ end
30
+ end
31
+ total.to_s
32
+ end
33
+
34
+ def random(length)
35
+ Array.new(length) { THIRTY_SIX[rand(THIRTY_SIX.size - 1)] }.join
36
+ end
37
+
38
+ module_function :encode, :decode, :random
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,7 @@
1
+ module Seofy
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ load "tasks/seofy.rake"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,36 @@
1
+ module Seofy
2
+ class TaskRunner
3
+ attr_reader :klasses
4
+ def initialize
5
+ @klasses = ENV["MODELS"]
6
+ end
7
+
8
+ def each_model
9
+ self.klasses.split(",").each do |class_name|
10
+ klass = class_name.constantize
11
+ yield klass if block_given?
12
+ end
13
+ end
14
+
15
+ def update_all
16
+ each_model do |klass|
17
+ klass.find_each do |record|
18
+ update(record)
19
+ end
20
+ end
21
+ end
22
+
23
+ def update_null
24
+ each_model do |klass|
25
+ klass.find_each(:conditions => ["#{klass.seofy_adapter.column} is null"]) do |record|
26
+ update(record)
27
+ end
28
+ end
29
+ end
30
+
31
+ def update(record)
32
+ record.class.seofy_adapter.set_seofy_slug(record)
33
+ record.save(:validate => false)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module Seofy
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,10 @@
1
+ namespace :seofy do
2
+ desc "update all slug, specify models use ENV['MODELS']"
3
+ task :update_all => :environment do
4
+ Seofy::TaskRunner.new.update_all
5
+ end
6
+ desc "update null slug, specify models use ENV['MODELS']"
7
+ task :update_null => :environment do
8
+ Seofy::TaskRunner.new.update_null
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "seofy/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "seofy"
7
+ s.version = Seofy::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Allen Wei"]
10
+ s.email = ["digruby@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{A flexiable permalink plugin for Rails}
13
+ s.description = %q{https://github.com/allenwei/seofy}
14
+
15
+ s.rubyforge_project = "seofy"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "babosa", "~> 0.3.0"
23
+ s.add_dependency "activerecord", "~> 3.0.0"
24
+ s.add_dependency "activesupport", "~> 3.0.0"
25
+ s.add_development_dependency "sqlite3"
26
+ s.add_development_dependency "rspec", "~> 2.5.0"
27
+ s.add_development_dependency "guard"
28
+ s.add_development_dependency "growl"
29
+ end
@@ -0,0 +1,2 @@
1
+ adapter: sqlite3
2
+ database: ":memory:"
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe "slug use base36", :integration => true do
4
+ before(:all) do
5
+ @store = Store.create!(:title => "a store")
6
+ end
7
+ it "should generate slug automaticly use base36" do
8
+ @store.slug.length.should == 3
9
+ @store.to_param.should == "a-store-#{@store.slug}"
10
+ end
11
+
12
+ describe "for_slug" do
13
+ it "should find the record" do
14
+ Store.for_slug(@store.to_param).should == @store
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe "slug for existing_column", :integration => true do
4
+ before(:all) do
5
+ @user = User.create!(:name => "a user name", :slug => "slug")
6
+ end
7
+
8
+ describe "to_param" do
9
+ it "should equal to combined slugs" do
10
+ @user.to_param.should == "a-user-name-slug"
11
+ end
12
+ end
13
+
14
+ describe "for_slug" do
15
+ it "should find the record" do
16
+ User.for_slug(@user.to_param).should == @user
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Seofy::ActiveRecord do
4
+ context "after mxin ActiveRecord::Base" do
5
+ it "should have class method :seofy" do
6
+ ActiveRecord::Base.should be_respond_to(:seofy)
7
+ end
8
+ end
9
+ context "a class extend Seofy::ActiveRecord::ClassMethods" do
10
+ before(:each) do
11
+ @klass = Class.new
12
+ @klass.extend Seofy::ActiveRecord::ClassMethods
13
+ @klass.should_receive(:init_seofy_config)
14
+ @klass.should_receive(:after_save)
15
+ @klass.should_receive(:before_save)
16
+ @klass.seofy
17
+ end
18
+
19
+ context "klass methods" do
20
+ subject { @klass }
21
+ it { should be_respond_to(:seofy) }
22
+
23
+ describe "seofy_adapter" do
24
+ it "should get adapter from config" do
25
+ @klass.should_receive(:seofy_config).and_return double(:adapter => "dummy adapter")
26
+ @klass.seofy_adapter
27
+ end
28
+ end
29
+
30
+ describe "for_slug" do
31
+ it "should get slug from id and find record use it" do
32
+ @klass.should_receive(:seofy_adapter).and_return double(:column => "id")
33
+ @klass.should_receive("find_by_id").with("123")
34
+ @klass.for_slug("a-b-c-123")
35
+ end
36
+ end
37
+ end
38
+
39
+ context "instance methods" do
40
+ subject {@klass.new }
41
+ it { should be_respond_to(:to_param)}
42
+ it { should be_respond_to(:seofy_slug)}
43
+ it { should be_respond_to(:seofy_source)}
44
+ end
45
+
46
+ describe "#seofy_source" do
47
+ it "will get source from inst" do
48
+ inst = @klass.new
49
+ @klass.should_receive(:seofy_config).and_return double(:source =>:name)
50
+ inst.should_receive(:name).and_return("a name")
51
+ inst.seofy_source.should == "a name"
52
+ end
53
+ end
54
+
55
+ describe "#seofy_slug" do
56
+ it "should get seofy_slug from adapter" do
57
+ inst = @klass.new
58
+ @klass.should_receive(:seofy_adapter).and_return double(:seofy_slug => "abc")
59
+ inst.seofy_slug.should == "abc"
60
+ end
61
+ end
62
+
63
+ describe "#to_param" do
64
+ it "should normalize source and join with slug" do
65
+ inst = @klass.new
66
+ inst.should_receive(:seofy_slug).and_return("abc")
67
+ inst.should_receive(:seofy_source).and_return("a normalize name")
68
+ inst.to_param.should == "a-normalize-name-abc"
69
+ end
70
+ end
71
+
72
+ it "should ask adapter handle callback" do
73
+ inst = @klass.new
74
+ @klass.should_receive(:seofy_adapter).and_return double(:before_save => true)
75
+ @klass.should_receive(:seofy_adapter).and_return double(:after_save => true)
76
+ inst.seofy_before_save
77
+ inst.seofy_after_save
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Seofy::Adapters::Base36 do
4
+ describe "#initialize" do
5
+ let(:adapter) { Seofy::Adapters::Base36.new(:length => 3, :column => :slug) }
6
+
7
+ it { adapter.length.should == 3 }
8
+ it { adapter.column.should == :slug }
9
+
10
+ describe "#set_seofy_slug" do
11
+ it "should generate random 3 characters" do
12
+ stub = Object.new
13
+ ::Seofy::Encoders::Base36.should_receive(:random).with(3).and_return("abc")
14
+ stub.should_receive("slug=").with("abc")
15
+ adapter.set_seofy_slug(stub)
16
+ end
17
+ end
18
+
19
+ describe "#seofy_slug" do
20
+ it "should equal to slug column" do
21
+ stub = Object.new
22
+ stub.should_receive(:slug).and_return("abc")
23
+ adapter.seofy_slug(stub).should == "abc"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Seofy::Adapters::Base do
4
+ context "methods" do
5
+ subject { Seofy::Adapters::Base.new }
6
+
7
+ it { should be_respond_to(:seofy_slug) }
8
+ it { should be_respond_to(:set_seofy_slug) }
9
+ it { should be_respond_to(:before_save) }
10
+ it { should be_respond_to(:after_save) }
11
+ end
12
+
13
+ describe "#before_save" do
14
+ it "should set_seofy_slug" do
15
+ adapter = Seofy::Adapters::Base.new
16
+ adapter.should_receive(:set_seofy_slug)
17
+ adapter.before_save("anything")
18
+ end
19
+ end
20
+
21
+ end
22
+
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Seofy::Adapters::ExistingColumn do
4
+ it "should get column from options" do
5
+ inst = Seofy::Adapters::ExistingColumn.new(:column => :id)
6
+ inst.column.should == :id
7
+ end
8
+
9
+
10
+ describe "seofy_slug" do
11
+ it "should get seofy_slug from existing data" do
12
+ stub = Object.new
13
+ stub.should_receive(:id).and_return(1)
14
+ adapter = Seofy::Adapters::ExistingColumn.new(:column => :id)
15
+ adapter.seofy_slug(stub).should == 1
16
+ end
17
+ end
18
+
19
+ describe "set_seofy_slug" do
20
+ it "should be false" do
21
+ adapter = Seofy::Adapters::ExistingColumn.new(:column => :id)
22
+ adapter.set_seofy_slug("anything").should be_false
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Seofy::Configuration do
4
+ describe "#initialize" do
5
+ it "should parse source, adapter and adapter options" do
6
+ params = {:source => :name, :adapter => :existing_column, :adapter_option => {:column => :id}}
7
+ stub_adapter = Seofy::Adapters::Base.new
8
+ Seofy::Adapters::ExistingColumn.should_receive(:new).with(params[:adapter_option]).and_return(stub_adapter)
9
+ conf = Seofy::Configuration.new(params)
10
+ conf.source.should == :name
11
+ conf.adapter.should == stub_adapter
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Seofy" do
4
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Seofy::TaskRunner do
4
+
5
+ describe "#update_all" do
6
+ it "should update all slugs" do
7
+ s1 = Store.create!("store 1")
8
+ slug1 = s1.slug
9
+ ENV["MODELS"] = "Store"
10
+ Seofy::TaskRunner.new.update_all
11
+ s1.reload.should_not == slug1
12
+ end
13
+ end
14
+
15
+ describe "#update_null" do
16
+ it "should update all null slugs" do
17
+ s1 = Store.create!("store 1")
18
+ Store.connection.execute("update stores set slug = NULL")
19
+ s1.reload.slug.should be_nil
20
+ s2 = Store.create!("store 1")
21
+ old_slug = s2.slug
22
+ ENV["MODELS"] = "Store"
23
+ Seofy::TaskRunner.new.update_all
24
+ s1.reload.should_not be_nil
25
+ s2.reload.slug.should_not == old_slug
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,9 @@
1
+ # existing_column adapter
2
+ class User < ActiveRecord::Base
3
+ seofy :source => :name, :adapter => :existing_column, :adapter_option => {:column => :slug}
4
+ end
5
+
6
+ # base36 adapter
7
+ class Store < ActiveRecord::Base
8
+ seofy :source => :title, :adapter => :base36, :adapter_option => {:length => 3, :column => :slug }
9
+ end
@@ -0,0 +1,15 @@
1
+ class CreateModels < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users, :force => true do |t|
4
+ t.string :name
5
+ t.string :slug
6
+ end
7
+
8
+ create_table :stores, :force => true do |t|
9
+ t.string :title
10
+ t.string :slug
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,24 @@
1
+ require 'rspec'
2
+ require 'logger'
3
+ require 'active_record'
4
+ require 'active_support'
5
+ require 'yaml'
6
+ require 'sqlite3'
7
+
8
+ $:.unshift File.expand_path("../../lib", __FILE__)
9
+ require 'seofy'
10
+
11
+ require 'models'
12
+ require 'models_migration'
13
+ dbconfig = YAML.load_file(File.expand_path("../database.yml",__FILE__))
14
+ ActiveRecord::Base.establish_connection(dbconfig)
15
+
16
+ ActiveRecord::Base.logger = Logger.new($stdout)
17
+
18
+
19
+ CreateModels.up
20
+
21
+ RSpec.configure do |c|
22
+ #c.filter_run_excluding :integration => true
23
+ end
24
+
metadata ADDED
@@ -0,0 +1,218 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: seofy
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Allen Wei
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-24 00:00:00 +08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: babosa
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 19
30
+ segments:
31
+ - 0
32
+ - 3
33
+ - 0
34
+ version: 0.3.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: activerecord
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 3
48
+ - 0
49
+ - 0
50
+ version: 3.0.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: activesupport
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 7
62
+ segments:
63
+ - 3
64
+ - 0
65
+ - 0
66
+ version: 3.0.0
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ type: :development
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ prerelease: false
86
+ requirement: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ~>
90
+ - !ruby/object:Gem::Version
91
+ hash: 27
92
+ segments:
93
+ - 2
94
+ - 5
95
+ - 0
96
+ version: 2.5.0
97
+ type: :development
98
+ version_requirements: *id005
99
+ - !ruby/object:Gem::Dependency
100
+ name: guard
101
+ prerelease: false
102
+ requirement: &id006 !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ type: :development
112
+ version_requirements: *id006
113
+ - !ruby/object:Gem::Dependency
114
+ name: growl
115
+ prerelease: false
116
+ requirement: &id007 !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ type: :development
126
+ version_requirements: *id007
127
+ description: https://github.com/allenwei/seofy
128
+ email:
129
+ - digruby@gmail.com
130
+ executables: []
131
+
132
+ extensions: []
133
+
134
+ extra_rdoc_files: []
135
+
136
+ files:
137
+ - .gitignore
138
+ - Gemfile
139
+ - Gemfile.lock
140
+ - Guardfile
141
+ - README.md
142
+ - Rakefile
143
+ - lib/seofy.rb
144
+ - lib/seofy/active_record.rb
145
+ - lib/seofy/adapter.rb
146
+ - lib/seofy/adapters/base.rb
147
+ - lib/seofy/adapters/base36.rb
148
+ - lib/seofy/adapters/existing_column.rb
149
+ - lib/seofy/configuration.rb
150
+ - lib/seofy/encoders/base36.rb
151
+ - lib/seofy/railtie.rb
152
+ - lib/seofy/task_runner.rb
153
+ - lib/seofy/version.rb
154
+ - lib/tasks/seofy.rake
155
+ - seofy.gemspec
156
+ - spec/database.yml
157
+ - spec/integration/base36_spec.rb
158
+ - spec/integration/existing_column_spec.rb
159
+ - spec/lib/seofy/active_record_spec.rb
160
+ - spec/lib/seofy/adapters/.base_spec.rb.swo
161
+ - spec/lib/seofy/adapters/base36_spec.rb
162
+ - spec/lib/seofy/adapters/base_spec.rb
163
+ - spec/lib/seofy/adapters/exiting_column_spec.rb
164
+ - spec/lib/seofy/configuration_spec.rb
165
+ - spec/lib/seofy/seofy_spec.rb
166
+ - spec/lib/seofy/task_runner_spec.rb
167
+ - spec/models.rb
168
+ - spec/models_migration.rb
169
+ - spec/spec_helper.rb
170
+ has_rdoc: true
171
+ homepage: ""
172
+ licenses: []
173
+
174
+ post_install_message:
175
+ rdoc_options: []
176
+
177
+ require_paths:
178
+ - lib
179
+ required_ruby_version: !ruby/object:Gem::Requirement
180
+ none: false
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ hash: 3
185
+ segments:
186
+ - 0
187
+ version: "0"
188
+ required_rubygems_version: !ruby/object:Gem::Requirement
189
+ none: false
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ hash: 3
194
+ segments:
195
+ - 0
196
+ version: "0"
197
+ requirements: []
198
+
199
+ rubyforge_project: seofy
200
+ rubygems_version: 1.6.2
201
+ signing_key:
202
+ specification_version: 3
203
+ summary: A flexiable permalink plugin for Rails
204
+ test_files:
205
+ - spec/database.yml
206
+ - spec/integration/base36_spec.rb
207
+ - spec/integration/existing_column_spec.rb
208
+ - spec/lib/seofy/active_record_spec.rb
209
+ - spec/lib/seofy/adapters/.base_spec.rb.swo
210
+ - spec/lib/seofy/adapters/base36_spec.rb
211
+ - spec/lib/seofy/adapters/base_spec.rb
212
+ - spec/lib/seofy/adapters/exiting_column_spec.rb
213
+ - spec/lib/seofy/configuration_spec.rb
214
+ - spec/lib/seofy/seofy_spec.rb
215
+ - spec/lib/seofy/task_runner_spec.rb
216
+ - spec/models.rb
217
+ - spec/models_migration.rb
218
+ - spec/spec_helper.rb