Friendly_id предотвращает редактирование / новых страниц из-за before_action:find_post

#ruby-on-rails #ruby #friendly-id

#ruby-on-rails #ruby #friendly-id

Вопрос:

Я использую драгоценный камень friendly_id для обработки фрагментов URL, и при применении исправления, позволяющего избежать 404-х, когда фрагмент изменяется из документации, мой код не работает должным образом.

Проблема в том, что он просто перенаправляет на просмотр записи, когда я нажимаю на кнопку редактирования, и не позволяет мне создать новую запись, потому что он «не может найти запись с идентификатором …», потому что он использует find_post метод.

У меня также есть friendly_id_slugs таблица для хранения истории.

В моей модели Post:

 class Post < ApplicationRecord
  extend FriendlyId
  friendly_id :title, use: :slugged

  ...

  def should_generate_new_friendly_id?
    slug.nil? || title_changed?
  end
end
  

Контроллер Post:

 class PostsController < ApplicationController
  before_action :find_post

  ...

  def find_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
end
  

Я пытался использовать, before_filter но меня спрашивают, имею ли я в виду, before_action и я попробовал find_post метод как в общедоступном, так и в private разделе моего контроллера.

Комментарии:

1. post_path это действие show , в то время как вы выполняете действие edit — поэтому это всегда будет перенаправлять. Вы действительно хотите, чтобы это before_action запускалось при edit действии?

2. @TomLord О нет, на самом деле я этого не делаю, поскольку это всегда будет актуальный URL через @post = Post.friendly.find(params[:id]) Я только хотел реализовать это из документов, чтобы решить любые старые URL-адреса в случае, если я их обновлю.

Ответ №1:

Мне кажется, что вы можете пропустить эту логику перенаправления для чего угодно, кроме show действия, поскольку redirect_to @post вас отправляет только на маршрут показа.

 def find_post
  @post = Post.find params[:id]

  if action_name == 'show' amp;amp; request.path != post_path(@post)
    return redirect_to @post, :status => :moved_permanently
  end
end
  

С другой стороны, вы можете отделить перенаправление от предварительной загрузки post чем-то вроде этого:

 before_action :find_post
before_action :redirect_to_canonical_route, only: :show

def find_post
  @post = Post.find params[:id]
end

def redirect_to_canonical_route
  if request.path != post_path(@post)
    return redirect_to @post, :status => :moved_permanently
  end
end
  

Комментарии:

1. Было бы более обычным писать before_action :find_post, only: :show

2. Возможно, @TomLord, но find_post также может быть полезно для других действий… вы просто не хотите перенаправлять для всех из них. Другим хорошим вариантом было бы извлечь это в отдельный before_action :redirect_to_canonical_route, only: :show .

3. @TomLord Я включил это в свой ответ в качестве альтернативы.

4. Каковы преимущества обработки поведения перенаправления отдельно от предварительной загрузки? Что-нибудь стоит дополнительного кода?

5. @TomLord Я должен согласиться с вами, мне нравится простота простого добавления , only: :show в мой код, чтобы все заработало.