我已在PostsController
上实施了friendly_id。
这就是我的PostsController
看起来的样子:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
load_and_authorize_resource
def index
@posts = Post.all.order("created_at desc")
end
def show
end
def new
@post = Post.new(parent_id: params[:parent_id])
end
def edit
end
def create
@post = current_user.posts.new(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to @post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_post
@post = Post.friendly.find(params[:id])
# If an old id or a numeric id was used to find the record, then
# the request path will not match the post_path, and we should do
# a 301 redirect that uses the current friendly id.
if request.path != post_path(@post)
return redirect_to @post, :status => :moved_permanently
end
end
def post_params
params.require(:post).permit(:status, :title, :photo, :file, :body, :parent_id)
end
end
这里发生了一些事情。
检查旧版网址并执行301重定向的重定向代码会干扰控制器的其他操作 - 例如edit
,如下所示:
if request.path != post_path(@post)
return redirect_to @post, :status => :moved_permanently
end
当我尝试编辑帖子时,会发生这种情况:
Started GET "/pnpyo-saddened-at-passing-of-roger-clarke/edit" for 127.0.0.1 at 2014-09-02 04:46:49 -0500
Processing by PostsController#edit as HTML
Parameters: {"id"=>"pnpyo-saddened-at-passing-of-roger-clarke"}
Post Load (1.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."slug" = 'pnpyo-saddened-at-passing-of-roger-clarke' ORDER BY "posts"."id" ASC LIMIT 1
Redirected to http://localhost:3000/pnpyo-saddened-at-passing-of-roger-clarke
Filter chain halted as :set_post rendered or redirected
Completed 301 Moved Permanently in 13ms (ActiveRecord: 1.2ms)
另外,出现的另一个问题是我安装了ancestry
gem。每当我尝试创建子帖子时,请使用与此类似的网址:http://localhost:3000/new?parent_id=pnpyo-saddened-at-passing-of-roger-clarke
这是产生的错误:
Started GET "/new?parent_id=pnpyo-saddened-at-passing-of-roger-clarke" for 127.0.0.1 at 2014-09-02 04:47:52 -0500
Processing by PostsController#new as HTML
Parameters: {"parent_id"=>"pnpyo-saddened-at-passing-of-roger-clarke"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
(0.4ms) SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL))) [["user_id", 1]]
Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT 1 [["id", 0]]
Completed 404 Not Found in 35ms
ActiveRecord::RecordNotFound - Couldn't find Post with 'id'=pnpyo-saddened-at-passing-of-roger-clarke:
() app/controllers/posts_controller.rb:19:in `new'
第19行是new
中的PostsController
动作......即:
@post = Post.new(parent_id: params[:parent_id])
这两个问题都与friendly_id
实施相关联。
如何一劳永逸地解决这两个问题?
答案 0 :(得分:1)
<强> Friendly_id 强>
首先,你必须意识到friendly_id
并不是一件大事。
它适用于changing your .find
ActiveRecord method,并且您可以将路线助手与slugs
一起使用。
这意味着您所拥有的任何混淆都不应该与friendly_id
有关 - 如果有任何问题,应该更多地处理您的系统(如果您设置正确,那么friendly_id不应该包含任何内容)你的电话等)
<强>修正强>
您需要考虑几个问题:
- 重定向
- ID
醇>
首先,不要在控制器中处理重定向。
我相信我之前回答了一个问题 - 你需要处理应用程序 routes 部分的重定向。为什么?这就是路由发生的地方。
尝试处理控制器中的重定向违反MVC principles(IMO) - 您将更好地处理重定向,如下所示:
#config/routes.rb
resources :posts, path: ''
get 'posts/:id' => redirect("/%{id}")
#get '/:id', to: 'posts#show' -> NOT NEEDED. Will be covered by the resources directive
#get 'posts/:id', to: 'posts#show' -> NOT NEEDED. Will be covered by redirect
#app/models/post.rb
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :slug, use: [:slugged, :finders]
end
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def show
@post = Post.find params[:id]
end
end
这将解决您的所有问题。
如果您使用friendly_id finders
模块,则无需区分任何自定义:friendly_id
参数或任何内容。它只会ping你的数据库id
和slug
- 没什么大不了的。
你大量过度复杂 - 你只需要将/posts/***
重定向到/:id
(无论如何都会转到posts
控制器)。这样,您的:id
仍然会以与没有 friendly_id
集成