Mostrar mensaje de error del método privado (Rails 6)

Tengo un método, create, que llama un método privado get_title:

def create

  @article = @user.articles.new(article_params)
  @article.title = get_title(@article.link)

  if @article.save
    redirect_to user_path, success: "Article Saved."
  else
    flash.now[:danger] = "Failed to save article."
  end

end

El get_title método funciona siempre que no haya errores en la solicitud de obtener:

def get_title(url)
  request = HTTParty.get(url)
  document = Nokogiri::HTML(request.body)
  title = document.at_css "title"
  return title.text
end

Puedo coger el error con un primer rescate antes de la llamada Nokogiri:

begin
  HTTParty.get(url)
rescue HTTParty::Error
  ...
rescue StandardError
  ...
else
  request = HTTParty.get(url)
end

No sé cómo detener el método y devolver el error al create método.

Cómo puedo devolver un error de la declaración de rescate a la create método y mostrar ese mensaje de error en un flash?

Pregunta hecha hace 3 años, 4 meses, 27 días - Por codeartisan


3 Respuestas:

  • Lo que probablemente quieras hacer es "distruir" este método para que no explote a menos que ocurra algo realmente inusual:

    class TitleFetchError < StandardError
    end
    
    def get_title(url)
      request = HTTParty.get(url)
    
      Nokogiri::HTML(request.body).at_css('title').text
    
    rescue HTTParty::Error => error
      raise TitleFetchError, error.to_s
    rescue StandardError => error
      raise TitleFetchError, error.to_s
    rescue ... (some other type of error, e.g. Nokogiri parse errors)
    end
    

    Donde en mi opinión eso debería ser realmente un método @article modelo, @article.fetch_title que haría lo mismo, usando su propio link propiedad.

    Una cosa a tener en cuenta es este patrón para escribir las acciones del controlador ayuda a simplificar las cosas:

    def create
      @article = @user.articles.new(article_params)
      @article.title = get_title(@article.link)
    
      @article.save!
      redirect_to user_path, success: "Article Saved."
    
    rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved
      redirect_to user_path, danger: "Failed to save article."
    rescue TitleFetchError => error
      redirect_to user_path, danger: "Failed to save article. Error: #{error}"
    end
    

    Donde usted tiene un buen camino "normal" limpio, y entonces sus excepciones se manejan en el lado si / cuando eso se hace necesario. Esto mantiene los dos flujos separados y evita el anidamiento adicional del if.

    Respondida el Dec 18, 2020 a las 13:52 - por nasean

    Votos positivos: 0 | Votos negativos: 0

  • Para devolver el mensaje de error al método create y mostrarlo en un flash, puedes hacer lo siguiente:

    • En tu método `get_title`, captura la excepción y devuelve `nil` en caso de error en lugar de lanzar la excepción. Esto permitirá controlar la excepción en el método `create`.
    ruby
    def get_title(url)
      begin
        request = HTTParty.get(url)
        document = Nokogiri::HTML(request.body)
        title = document.at_css "title"
        return title.text
      rescue StandardError => e
        Rails.logger.error("Error fetching title: {e.message}")    return nil
      end
    end
    
    • Luego, en tu método `create`, verifica si el título obtenido es `nil`. Si es así, establece un mensaje de error y redirige a una página de error o muestra un mensaje de error en el `flash`.
    ruby
    def create
      @article = @user.articles.new(article_params)
      title = get_title(@article.link)
    
      if title.nil?
        flash.now[:danger] = "Failed to fetch title for the article."
        render :new 

    Otra acción donde muestres el mensaje de error.

    else @article.title = title if @article.save redirect_to user_path, success: "Article Saved." else flash.now[:danger] = "Failed to save article." render :new

    Otra acción donde muestres el mensaje de error.

    end end end

    Con estos cambios, podrás manejar los errores al obtener el título y mostrar un mensaje de error apropiado en el flash al usuario. Asegúrate de ajustar el manejo de errores según tus necesidades exactas.

    Respondida el Dec 19, 2020 a las 13:52 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Puedes devolver un error desde un método privado utilizando raise, que detendrá la ejecución del método y devolverá el error al método de llamada. En este caso, podrías manejar el error en el método create de la siguiente manera:

    ruby
    def create
      begin
        @article = @user.articles.new(article_params)
        @article.title = get_title(@article.link)
    
        if @article.save
          redirect_to user_path, success: "Article Saved."
        else
          flash.now[:danger] = "Failed to save article."
        end
      rescue HTTParty::Error, StandardError => e
        flash.now[:danger] = "Error retrieving article title: {e.message}"  end
    end
    

    En el método get_title, puedes generar una excepción utilizando raise si se produce un error:

    ruby
    def get_title(url)
      begin
        request = HTTParty.get(url)
        document = Nokogiri::HTML(request.body)
        title = document.at_css "title"
        return title.text
      rescue HTTParty::Error, StandardError => e
        raise "Error retrieving article title: {e.message}"  end
    end
    

    Ahora, cualquier error que se produzca en el método get_title se propagará al método create y se mostrará en el flash de error.

    Respondida el Dec 19, 2020 a las 14:00 - por Gemini

    Votos positivos: 0 | Votos negativos: 0