Rails默认的数据id不是很安全,生成合适的slug很重要,对于中文来说显示拼音相对比较友好。以一个Page的数据为例说明。

Gemfile

一般关键的gem我都fork一份,防止以后不更新或者其他原因不能使用。

gem 'friendly_id',github: 'brucebot/friendly_id'

Console

rails g migration add_slug_to_pages slug:string
rails g friendly_id
bunlde exec rake db:migrate
rails c
Page.find_each(&:save)

friendly_id的Slugged中文处理

# config/initializers/friendly_id/slugged.rb
module FriendlyId
module Slugged
  def normalize_friendly_id(value)
    Pinyin.t(value.to_s).parameterize
  end
end
end

Migration

class AddSlugToPages < ActiveRecord::Migration
  def change
    add_column :pages, :slug, :string
    add_index :pages, :slug
  end
end
class CreateFriendlyIdSlugs < ActiveRecord::Migration
  def change
    create_table :friendly_id_slugs do |t|
      t.string   :slug,           :null => false
      t.integer  :sluggable_id,   :null => false
      t.string   :sluggable_type, :limit => 50
      t.string   :scope
      t.datetime :created_at
    end
    add_index :friendly_id_slugs, :sluggable_id
    add_index :friendly_id_slugs, [:slug, :sluggable_type], length: { slug: 140, sluggable_type: 50 }
    add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], length: { slug: 70, sluggable_type: 50, scope: 70 }, unique: true
    add_index :friendly_id_slugs, :sluggable_type
  end
end

Model

#page.rb
class Page < ActiveRecord::Base
extend FriendlyId
	friendly_id :title, use: :slugged
	def should_generate_new_friendly_id?
	  new_record? || slug.blank?
	end
end

如果之前有写to_param的方法,请删除。

Controller

#pages_controller.rb
class PagesController < ApplicationController
	def set_page
	@page = Page.friendly.find(params[:id])
	redirect_to action: [:edit,:show,:update,:destroy], id: @page.friendly_id, status: 301 unless @page.friendly_id == params[:id]
	end
end

不要忘记在生产环境中运行Page.find_each(&:save)

-END-