কীভাবে একটি 404 টি পুনর্নির্দেশ করবেন?


482

আমি রেলগুলিতে একটি 404 পৃষ্ঠা 'নকল' করতে চাই। পিএইচপি-তে, আমি কেবল ত্রুটি কোড সহ একটি শিরোনাম পাঠাব:

header("HTTP/1.0 404 Not Found");

এটি কীভাবে পেরেলগুলি দিয়ে করা হয়?

উত্তর:


1049

404 নিজেকে রেন্ডার করবেন না, এর কোনও কারণ নেই; রেলগুলির মধ্যে ইতিমধ্যে অন্তর্নির্মিত এই কার্যকারিতা রয়েছে। আপনি যদি 404 পৃষ্ঠা প্রদর্শন করতে চান তবে একটি render_404পদ্ধতি তৈরি করুন (বা not_foundযেমন আমি এটি বলেছিলাম) এর ApplicationControllerমতো:

def not_found
  raise ActionController::RoutingError.new('Not Found')
end

এছাড়াও হ্যান্ডলগুলি পাগল AbstractController::ActionNotFound, এবং ActiveRecord::RecordNotFoundএকই ভাবে।

এটি দুটি জিনিস আরও ভাল করে:

1) এটি rescue_from404 পৃষ্ঠাটি রেন্ডার করতে হ্যান্ডলারে অন্তর্নির্মিত রেলগুলি ব্যবহার করে এবং 2) এটি আপনার কোডটির সম্পাদনকে বাধা দেয়, আপনাকে সুন্দর কাজগুলি করতে দেয়:

  user = User.find_by_email(params[:email]) or not_found
  user.do_something!

কুরুচিপূর্ণ শর্তাধীন বিবৃতি না লিখে।

বোনাস হিসাবে, পরীক্ষাগুলি পরিচালনা করাও অত্যন্ত সহজ। উদাহরণস্বরূপ, আরএসপেক একীকরণ পরীক্ষায়:

# RSpec 1

lambda {
  visit '/something/you/want/to/404'
}.should raise_error(ActionController::RoutingError)

# RSpec 2+

expect {
  get '/something/you/want/to/404'
}.to raise_error(ActionController::RoutingError)

এবং সর্বনিম্ন:

assert_raises(ActionController::RoutingError) do 
  get '/something/you/want/to/404'
end

অথবা রেলগুলি থেকে 404 রেন্ডার থেকে আরও তথ্য পড়ুন কোনও নিয়ামক পদক্ষেপ থেকে পাওয়া যায় নি


3
এটি নিজে করার একটি কারণ আছে। যদি আপনার অ্যাপ্লিকেশনটি মূল থেকে সমস্ত রুটকে হাইজ্যাক করে। এটি খারাপ নকশা, তবে কখনও কখনও অ-এড়ানো যায় না।
সক্ষম

7
এই পদ্ধতির সাহায্যে আপনি অ্যাক্টিভেকর্ড ব্যাং ফাইন্ডারগুলি (সন্ধান করুন !, সন্ধান_বি _ _।! ইত্যাদি) ব্যবহার করতে পারবেন, যা সকলেই একটি অ্যাক্টিভেকর্ড :: রেকর্ডনটফাউন্ড ব্যতিক্রম উত্থাপন করে যদি কোনও রেকর্ড না পাওয়া যায় (রেসকিউ_ফর্ম হ্যান্ডলারের ট্রিগার))
gjvis

2
এটি আমার জন্য একটি 500 অভ্যন্তরীণ সার্ভার ত্রুটি উত্থাপন করে 404 নয় not আমি কী অনুপস্থিত?
গ্লেন

3
ActionController::RecordNotFoundভালো বিকল্প বলে মনে হচ্ছে ?
পিটার এহরলিচ

4
কোড কাজ করে মহান কিন্তু এই সময়ের মধ্যে আমি বুঝতে পারলাম আমি RSpec 2 যা বিভিন্ন সিনট্যাক্স হয়েছে ব্যবহার করছিলেন পরীক্ষা করেনি: expect { visit '/something/you/want/to/404' }.to raise_error(ActionController::RoutingError)মাধ্যমে / stackoverflow.com/a/1722839/993890
ryanttb

243

HTTP 404 স্থিতি

একটি 404 শিরোনাম ফিরিয়ে দিতে, :statusরেন্ডার পদ্ধতির জন্য কেবল বিকল্পটি ব্যবহার করুন।

def action
  # here the code

  render :status => 404
end

আপনি যদি মান 404 পৃষ্ঠাটি রেন্ডার করতে চান তবে আপনি কোনও পদ্ধতিতে বৈশিষ্ট্যটি বের করতে পারেন।

def render_404
  respond_to do |format|
    format.html { render :file => "#{Rails.root}/public/404", :layout => false, :status => :not_found }
    format.xml  { head :not_found }
    format.any  { head :not_found }
  end
end

এবং এটি আপনার কর্ম হিসাবে কল

def action
  # here the code

  render_404
end

আপনি যদি ক্রিয়াটি ত্রুটি পৃষ্ঠাটি রেন্ডার এবং বন্ধ করতে চান তবে কেবল একটি রিটার্ন স্টেটমেন্ট ব্যবহার করুন।

def action
  render_404 and return if params[:something].blank?

  # here the code that will never be executed
end

অ্যাক্টিভেকর্ড এবং এইচটিটিপি 404

এছাড়াও মনে রাখবেন যে রেলগুলি কিছু অ্যাক্টিভেকর্ড ত্রুটিগুলি উদ্ধার করে, যেমন ActiveRecord::RecordNotFound404 ত্রুটি পৃষ্ঠা প্রদর্শন করে।

এর অর্থ এই ক্রিয়াটি নিজেকে উদ্ধার করার দরকার নেই

def show
  user = User.find(params[:id])
end

User.findActiveRecord::RecordNotFoundযখন ব্যবহারকারী উপস্থিত না থাকে তখন উত্থাপন করে। এটি একটি খুব শক্তিশালী বৈশিষ্ট্য। নীচের কোডটি দেখুন

def show
  user = User.find_by_email(params[:email]) or raise("not found")
  # ...
end

আপনি চেকটি রেলগুলিতে অর্পণ করে এটিকে সহজ করতে পারেন। সহজভাবে ঠুং শব্দ সংস্করণ ব্যবহার করুন।

def show
  user = User.find_by_email!(params[:email])
  # ...
end

9
এই সমাধানটিতে একটি বড় সমস্যা রয়েছে; এটি এখনও টেমপ্লেটে কোড চালাবে। সুতরাং আপনার যদি একটি সাধারণ, বিশ্রামের কাঠামো থাকে এবং কেউ অস্তিত্বহীন একটি আইডি প্রবেশ করে তবে আপনার টেমপ্লেটটি সেই অজানাটির সন্ধান করবে যা বিদ্যমান নেই।
jcalvers

5
পূর্বে উল্লিখিত হিসাবে, এটি সঠিক উত্তর নয়। স্টিভেন চেষ্টা করুন।
পাবলো মারাম্বিও

উন্নত অনুশীলন প্রতিফলিত করার জন্য নির্বাচিত উত্তর পরিবর্তন করা হয়েছে। মন্তব্যের জন্য ধন্যবাদ, বলছি!
যুবাল কর্মী

1
আমি উত্তরটি আরও উদাহরণ এবং অ্যাক্টিভেকর্ড সম্পর্কে একটি নোট সহ আপডেট করেছি।
সিমোন কার্লেটি

1
ঠাট্টা সংস্করণ কোড সম্পাদন বন্ধ করে দেয়, সুতরাং এটি আরও কার্যকর সমাধান আইএমএইচও।
গুই ভাইরা

60

স্টিভেন সোরোকার জমা দেওয়া নতুন নির্বাচিত উত্তরটি নিকটে, তবে সম্পূর্ণ নয়। পরীক্ষা নিজেই এই সত্যটি লুকিয়ে রাখে যে এটি সত্য 404 ফিরিয়ে দিচ্ছে না - এটি 200 - "সাফল্য" এর একটি স্থিতি ফিরিয়ে দিচ্ছে। মূল উত্তরটি কাছাকাছি ছিল, তবে বিন্যাসটি এমনভাবে সরবরাহ করার চেষ্টা করেছিল যেন কোনও ব্যর্থতা ঘটেনি। এটি সবকিছু স্থির করে:

render :text => 'Not Found', :status => '404'

আরএসপেক এবং কাঁদা ম্যাথার্স ব্যবহার করে 404 ফেরত প্রত্যাশা করি এমন কিছুর জন্য এখানে আমার একটি সাধারণ পরীক্ষার সেট রয়েছে:

describe "user view" do
  before do
    get :show, :id => 'nonsense'
  end

  it { should_not assign_to :user }

  it { should respond_with :not_found }
  it { should respond_with_content_type :html }

  it { should_not render_template :show }
  it { should_not render_with_layout }

  it { should_not set_the_flash }
end

এই স্বাস্থ্যকর প্যারানোয়াটি আমাকে অন্য বিষয়গুলি পীচি লাগলে সামগ্রী-ধরণের অমিলটি স্পট করার অনুমতি দেয় :) আমি এই সমস্ত উপাদানগুলির জন্য যাচাই করি: নির্ধারিত ভেরিয়েবল, প্রতিক্রিয়া কোড, প্রতিক্রিয়া সামগ্রী প্রকার, টেমপ্লেট রেন্ডার, লেআউট রেন্ডার, ফ্ল্যাশ বার্তা।

আমি কখনও কখনও কখনও কঠোরভাবে এইচটিএমএল এমন অ্যাপ্লিকেশনগুলিতে সামগ্রী প্রকারের চেক এড়িয়ে যাব। সর্বোপরি, "একজন সন্দিহান সমস্ত দারাগুলি পরীক্ষা করে" :)

http://dilbert.com/strips/comic/1998-01-20/

এফওয়াইআই: আমি নিয়ামকের মধ্যে যা ঘটে চলেছে তার জন্য পরীক্ষার প্রস্তাব দিই না, "" should_raise "। আপনি যা যত্নশীল তা আউটপুট। উপরের আমার পরীক্ষাগুলি আমাকে বিভিন্ন সমাধানের চেষ্টা করার অনুমতি দিয়েছে এবং সমাধানগুলি কোনও ব্যতিক্রম, বিশেষ উপস্থাপনা ইত্যাদির উত্থাপন করছে কিনা তা পরীক্ষাগুলি একই থাকে the


3
সত্যিই এই উত্তরটি পছন্দ করুন, বিশেষত আউটপুট পরীক্ষার জন্য এবং
নিয়ামককে

পাগল বিল্ট-ইন করেছে 404 স্থিতি: render :text => 'Not Found', :status => :not_found
লাসে বাঙ্ক

1
@ জাইমবেলমিয়ার - আমি নিশ্চিত যে আপনি যখন মোতায়েন (অর্থাৎ স্টেজিং / প্রোড) পরিবেশে থাকেন তখন এটি 200 ফিরিয়ে দেয় না । আমি এটি বেশ কয়েকটি অ্যাপ্লিকেশনগুলিতে করি এবং এটি গ্রহণযোগ্য সমাধানে বর্ণিত হিসাবে কাজ করে। সম্ভবত আপনি যা উল্লেখ করছেন তা হ'ল এটি 200 ফেরত দেয় যখন এটি যখন ডেবেগ স্ক্রিনটিকে বিকাশে দেয় যেখানে আপনার config.consider_all_requests_localপ্যারামিটারটি সম্ভবত আপনার environments/development.rbফাইলে সেট করা আছে । মঞ্চায়ন / উত্পাদনের ক্ষেত্রে গৃহীত সমাধানে বর্ণিত হিসাবে আপনি যদি কোনও ত্রুটি বাড়িয়ে থাকেন তবে আপনি অবশ্যই একটি 200 নয় একটি 404 পাবেন
জাভিদ জামায়ে

18

আপনি রেন্ডার ফাইলটিও ব্যবহার করতে পারেন:

render file: "#{Rails.root}/public/404.html", layout: false, status: 404

আপনি যেখানে লেআউটটি ব্যবহার করতে বা চয়ন করতে পারেন।

আর একটি বিকল্প এটি নিয়ন্ত্রণ করতে ব্যতিক্রমগুলি ব্যবহার করা হয়:

raise ActiveRecord::RecordNotFound, "Record not found."

13

নির্বাচিত উত্তরটি 3.3+ রেলগুলিতে কাজ করে না কারণ ত্রুটি হ্যান্ডলারটি মিডওয়্যারটিতে স্থানান্তরিত হয়েছিল ( গিথুব সমস্যাটি দেখুন )।

আমি যে সমাধানটি পেয়েছি তাতে আমি বেশ খুশি Here

ইন ApplicationController:

  unless Rails.application.config.consider_all_requests_local
    rescue_from Exception, with: :handle_exception
  end

  def not_found
    raise ActionController::RoutingError.new('Not Found')
  end

  def handle_exception(exception=nil)
    if exception
      logger = Logger.new(STDOUT)
      logger.debug "Exception Message: #{exception.message} \n"
      logger.debug "Exception Class: #{exception.class} \n"
      logger.debug "Exception Backtrace: \n"
      logger.debug exception.backtrace.join("\n")
      if [ActionController::RoutingError, ActionController::UnknownController, ActionController::UnknownAction].include?(exception.class)
        return render_404
      else
        return render_500
      end
    end
  end

  def render_404
    respond_to do |format|
      format.html { render template: 'errors/not_found', layout: 'layouts/application', status: 404 }
      format.all { render nothing: true, status: 404 }
    end
  end

  def render_500
    respond_to do |format|
      format.html { render template: 'errors/internal_server_error', layout: 'layouts/application', status: 500 }
      format.all { render nothing: true, status: 500}
    end
  end

এবং ইন application.rb:

config.after_initialize do |app|
  app.routes.append{ match '*a', :to => 'application#not_found' } unless config.consider_all_requests_local
end

এবং আমার সংস্থানগুলিতে (দেখান, সম্পাদনা করুন, আপডেট করুন, মুছুন):

@resource = Resource.find(params[:id]) or not_found

এটি অবশ্যই উন্নত করা যেতে পারে, তবে কমপক্ষে, মূল রেল ফাংশনগুলিকে ওভাররাইড না করে আমার কাছে নোট_ফাউন্ড এবং ইন্টারনাল_অরারের পক্ষে বিভিন্ন মতামত রয়েছে।


3
এটি একটি খুব সুন্দর সমাধান; তবে আপনার || not_foundঅংশটি প্রয়োজন নেই , কেবল কল করুন find!(ব্যাংকে লক্ষ্য করুন) এবং এটি অ্যাক্টিভেকর্ড :: রেকর্ডনটফাউন্ড নিক্ষেপ করবে যখন সংস্থানটি পুনরুদ্ধার করা যায় না। এছাড়াও, যদি শর্তে অ্যাক্টিভেকর্ড :: রেকর্ডনটফাউন্ড অ্যারেতে যুক্ত করুন।
মারেক পহোদা

1
আমি উদ্ধার করব StandardErrorএবং না Exception, কেবল ক্ষেত্রেই। প্রকৃতপক্ষে আমি স্ট্যান্ডার্ড 500 স্ট্যাটিক পৃষ্ঠাটি ছেড়ে দেব এবং একেবারেই কাস্টম ব্যবহার render_500করব না, এর অর্থ আমি স্পষ্টভাবে rescue_from404 এর সাথে সম্পর্কিত ত্রুটির অ্যারে করব
ড। স্ট্রেনজয়েভ

7

এগুলি আপনাকে সাহায্য করবে ...

অ্যাপ্লিকেশন নিয়ামক

class ApplicationController < ActionController::Base
  protect_from_forgery
  unless Rails.application.config.consider_all_requests_local             
    rescue_from ActionController::RoutingError, ActionController::UnknownController, ::AbstractController::ActionNotFound, ActiveRecord::RecordNotFound, with: lambda { |exception| render_error 404, exception }
  end

  private
    def render_error(status, exception)
      Rails.logger.error status.to_s + " " + exception.message.to_s
      Rails.logger.error exception.backtrace.join("\n") 
      respond_to do |format|
        format.html { render template: "errors/error_#{status}",status: status }
        format.all { render nothing: true, status: status }
      end
    end
end

ত্রুটিগুলি নিয়ন্ত্রণকারী

class ErrorsController < ApplicationController
  def error_404
    @not_found_path = params[:not_found]
  end
end

মতামত / ত্রুটি / error_404.html.haml

.site
  .services-page 
    .error-template
      %h1
        Oops!
      %h2
        404 Not Found
      .error-details
        Sorry, an error has occured, Requested page not found!
        You tried to access '#{@not_found_path}', which is not a valid page.
      .error-actions
        %a.button_simple_orange.btn.btn-primary.btn-lg{href: root_path}
          %span.glyphicon.glyphicon-home
          Take Me Home

3
<%= render file: 'public/404', status: 404, formats: [:html] %>

404 ত্রুটি পৃষ্ঠায় আপনি যে পৃষ্ঠায় রেন্ডার করতে চান তা কেবল এই পৃষ্ঠায় যুক্ত করুন এবং আপনার কাজ শেষ হয়েছে।


1

আমি প্রশাসক নন এমন যে কোনও লগ ইন হওয়া ব্যবহারকারীর জন্য একটি 'সাধারণ' 404 নিক্ষেপ করতে চেয়েছিলাম, সুতরাং আমি এই জাতীয় 5 টির মতো লিখেছিলাম:

class AdminController < ApplicationController
  before_action :blackhole_admin

  private

  def blackhole_admin
    return if current_user.admin?

    raise ActionController::RoutingError, 'Not Found'
  rescue ActionController::RoutingError
    render file: "#{Rails.root}/public/404", layout: false, status: :not_found
  end
end


0

ত্রুটি পরিচালনার পরীক্ষা করার জন্য, আপনি এর মতো কিছু করতে পারেন:

feature ErrorHandling do
  before do
    Rails.application.config.consider_all_requests_local = false
    Rails.application.config.action_dispatch.show_exceptions = true
  end

  scenario 'renders not_found template' do
    visit '/blah'
    expect(page).to have_content "The page you were looking for doesn't exist."
  end
end

0

আপনি যদি বিভিন্নভাবে বিভিন্ন 404 টি পরিচালনা করতে চান তবে সেগুলি আপনার নিয়ামকগুলিতে ধরা বিবেচনা করুন। এটি আপনাকে বিভিন্ন ব্যবহারকারী গোষ্ঠী দ্বারা উত্পাদিত 404 টির সংখ্যা ট্র্যাক করার, ব্যবহারকারীদের সাথে কী ভুল হয়েছে / ব্যবহারকারী অভিজ্ঞতার কোন অংশে টুইঙ্কের প্রয়োজন হতে পারে, এ / বি পরীক্ষার ব্যবস্থা ইত্যাদির সাহায্যে যোগাযোগের সহায়তা দেওয়ার মতো জিনিসগুলি করতে অনুমতি দেবে etc.

আমি অ্যাপ্লিকেশন নিয়ন্ত্রণকারীটিতে বেস লজিকটি এখানে রেখেছি, তবে এটি কেবলমাত্র একটি নিয়ামকের জন্য বিশেষ যুক্তি রাখতে আরও নির্দিষ্ট নিয়ামকগুলিতে স্থাপন করা যেতে পারে।

ENV ['RESCUE_404'] এর সাথে যদি আমি কোনও ব্যবহার করছি, তাই আমি বিচ্ছিন্নভাবে এআর :: রেকর্ডনটফাউন্ডের উত্থাপন পরীক্ষা করতে পারি। পরীক্ষাগুলিতে, আমি এই ENV ভারটিকে মিথ্যাতে সেট করতে পারি এবং আমার উদ্ধার_ক্রমে আগুন লাগবে না। এইভাবে আমি উত্থাপনকে শর্তযুক্ত 404 যুক্তি থেকে পৃথক করতে পারি।

class ApplicationController < ActionController::Base

  rescue_from ActiveRecord::RecordNotFound, with: :conditional_404_redirect if ENV['RESCUE_404']

private

  def conditional_404_redirect
    track_404(@current_user)
    if @current_user.present?
      redirect_to_user_home          
    else
      redirect_to_front
    end
  end

end
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.