使用场景:在url中显示post的title,而不是post的id,比如url中,使用posts/one, 而不是post/1。另外一个应用到的场景中是,当post的title改变的时候,访问post旧的title可以链接到已经更新为新的title的post中,原理是使用history。

代码如下所示:

#gemfile
gem 'friendly_id', '~> 5.1.0' # Note: You MUST use 5.0.0 or greater for Rails 4.0+

#终端
rails g friendly_id  #需要修改ActiveRecord::Migration为ActiveRecord::Migration[5.1]
rails g scaffold post title:string body:text description:text slug:string:uniq

#model中的post.rb
class Post < ApplicationRecord
  extend FriendlyId
  friendly_id :title, use: [:slugged, :history] #添加history为记录旧值

  def should_generate_new_friendly_id?
    title_changed?
  end
end

#controller中posts_controller.rb
class PostsController < ApplicationController
  def show
    if request.path != post_path(@post) #当访问旧值时,链接地址会自动跳到更新后的新值中
      redirect_to @post, :status => :moved_permanently
    end
  end

  def update
    @post.slug = nil #必须添加
    if @post.update_attributes(post_params)
      flash[:notice] = 'Post successfully updated'
      redirect_to @post
    else
      render 'edit'
    end
  end

  private
    def set_post
      @post = Post.friendly.find(params[:id]) #必须在添加friendly方法
    end
end

解决中文可以作为friendly_id的问题

#gemfile
gem 'babosa'

#model
class Product < ActiveRecord::Base
  extend FriendlyId

  #原本是input.to_s.parameterize,但是parameterize只支持英文跟數字,所以改用babosa的to_slug
  def normalize_friendly_id(input)
    input.to_s.to_slug.normalize.to_s
  end
end

friendly_id的局限

#不能使用find_by方法
User.find_by(id: params[:id]) #会报错

results matching ""

    No results matching ""