2010-08-04 42 views
11

Trong bộ điều khiển bộ điều khiển, tôi đã sử dụng Date.new để tạo đối tượng ngày được chuyển trong ActiveRecord của mình.tăng ActiveRecord :: RecordNotFound (hoặc bất kỳ trạng thái 404) nào cho ngày không hợp lệ

end_range = Date.new(params[:year].to_i, params[:month].to_i, params[:day].to_i).end_of_day.to_formatted_s(:db) 

Vấn đề với điều này trên là nếu người dùng cố gắng để thay đổi các thông số trong URL bằng tay, chẳng hạn như nhập 40 cho param ngày, Date.new thất bại (như mong đợi). Tuy nhiên, tôi không muốn có một lỗi 500 nếu người dùng gõ vào một cái gì đó như thế, nhưng thay vì một lỗi 404 (vì bạn sẽ không bao giờ thực sự có thể có một kỷ lục với một ngày 40).

Tôi đã thử nhiều điều kiện khác nhau (ifunless báo cáo) đến raise ActiveRecord::RecordNotFound nếu không thành công, nhưng trả về lỗi 500 trước khi chạy điều kiện (và không bao giờ trả về 404).

Có ai biết cách nào tốt hơn để xử lý điều đó hay cách để cho phép Date.new thất bại hơn để câu lệnh có điều kiện có thể chạy?

Trả lời

28

Trong trường hợp này bạn có thể cứu một ngoại lệ và nâng cao khác nếu bạn muốn tái bản đồ ngoại lệ mà không được xử lý vào loại đó là:

def show 
    begin 
    end_range = Date.new(...) 
    rescue ArgumentError 
    # Invalid date 
    raise ActiveRecord::RecordNotFound 
    end 
rescue ActiveRecord::RecordNotFound 
    render(:partial => 'not_found', :layout => 'application', :status => :not_found) 
end 

Nó có thể là hiệu quả hơn để đơn giản render và thất bại ngay lập tức.

def show 
    begin 
    end_range = Date.new(...) 
    rescue ArgumentError 
    return render(:partial => 'date_not_found', :layout => 'application', :status => :not_found) 
    end 
end 

Bạn cũng có thể làm điều này trong một cảm giác sâu rộng hơn bằng cách sử dụng phương pháp rescue_from của ApplicationController:

class ApplicationController < ActionController::Base 
    rescue_from 'ArgumentError do 
    render(:partial => 'exceptions/argument_error', :layout => 'application', :status => :not_found) 
    end 
end 
+0

Cảm ơn, mà làm việc. Ví dụ thứ hai hoạt động tuyệt vời, đó là những gì tôi đã đi, nhưng tôi bắt đầu chỉ cố gắng thông qua một NotRound ActiveRecord chỉ để có được một cái gì đó khác hơn 500. (Nếu ai đọc, điều này, ActiveRecord là mistyped trong ví dụ đầu tiên.) –

+0

cố định lỗi đánh máy. Rất vui được làm việc cho bạn. – tadman

1

Tôi nghĩ rằng nó có ý nghĩa hơn để giải cứu một lỗi ngày không hợp lệ với một thông điệp hữu ích. Đây là một vấn đề phổ biến khi mọi người chọn ngày 30 tháng 2 chẳng hạn. Tôi thà gửi chúng trở lại biểu mẫu được đề cập và cho họ biết lý do tại sao họ được gửi lại. 404 sẽ là sai trong hầu hết các trường hợp, vì lỗi này là đầu vào của người dùng không hợp lệ, không phải là URL không hợp lệ.

Hơn nữa, nếu bạn giải cứu tất cả ArgumentError giây thì bạn sẽ không nhận được thông báo về các lỗi liên quan đến mã khác. Vì vậy, nếu nó không phải là một lỗi ngày thì tôi lại nâng lỗi. Thật không may, chúng ta phải thay đổi kiểu ngoại lệ để tránh một vòng lặp.

Tôi đã đặt này trong application_controller:

rescue_from ArgumentError do |exception| 
    if exception.message == 'invalid date' 
    flash[:error] = exception.message 
    redirect_to request.referer ? :back : root_url 
    else 
    raise StandardError, exception.message, exception.backtrace 
    end 
end 
+1

câu trả lời này là tốt hơn, nhiều Rails định hướng! – caesarsol

+1

Chuẩn không được khuyến nghị. Họ chỉ là quá cơ bản và không giải thích bất kỳ bối cảnh nào, chỉ thực tế là một số ngoại lệ đã được nâng lên. – maikovich

Các vấn đề liên quan