2010-11-08 36 views
7

Tôi đang ở trên Rails 2.3.5. Trong một bộ điều khiển sử dụng điển hình tạo ra hành độngLỗi chuỗi JSON không hợp lệ trong Rails

class UsersController 
    def create 
    @user = User.new(params[:user]) 
    respond_to do |format] 
     if @user.save ... 
     else 
     format.json .... 
     end   
    end 
end 

Khi một khách hàng đi một/chuỗi JSON bị thay đổi không hợp lệ cho đầu vào, Rails ném một lỗi 500 máy chủ nội bộ nói "chuỗi JSON không hợp lệ". Tôi có thể bẫy lỗi để tôi có thể đưa ra thông báo tùy chỉnh không?

CẬP NHẬT Đây là ngăn xếp theo yêu cầu. Tôi biết đây là một chuỗi JSON không đúng định dạng, câu hỏi của tôi không phải là cách sửa chuỗi JSON mà là cách bẫy lỗi cụ thể này để tôi có thể gửi lại một thông báo lỗi có ý nghĩa hơn lỗi HTTP 500 Internal Server . Cảm ơn trước sự giúp đỡ của bạn

Error occurred while parsing request parameters. 
Contents: 

user: {login: "John", email: "[email protected]", password: "111"}} 
/!\ FAILSAFE /!\ Mon Nov 08 02:01:04 -0800 2010 

    Status: 500 Internal Server Error 
    Invalid JSON string 
    c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/json/backends/yaml.rb:14:in `decode' 
    c:1:in `__send__' 
    c:1:in `decode' 
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/params_parser.rb:42:in `parse_formatted_parameters' 
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/params_parser.rb:11:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/session/cookie_store.rb:93:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/failsafe.rb:26:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `synchronize' 
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:114:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/reloader.rb:34:in `run' 
    c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:108:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/rails/rack/static.rb:31:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:46:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `each' 
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `call' 
    c:/ruby/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/rails/rack/log_tailer.rb:17:in `call' 
    ... 
    c:/ruby/lib/ruby/gems/1.8/gems/rack-1.0.1/lib/rack/handler/mongrel.rb:34:in `run' 
    c:/ruby/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/commands/server.rb:111 
    c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' 
    c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' 
    script/server:3 
re.rb:31:in `require' 
    script/server:3 
+0

bạn có thể đặt backtrace hoàn chỉnh không? – shingara

Trả lời

6

Tôi đã tìm thấy plugin này để hoạt động trên đường ray 3.0.5: https://github.com/kares/request_exception_handler

Khi Rob Cameron đề nghị tải ứng dụng đường ray của bạn và tăng parseError từ mã ứng dụng của bạn. Tôi đã không thử nghiệm nó tác động hiệu suất, nhưng nó dường như hoạt động tốt.

+0

Plugin này hoạt động như một sự quyến rũ! – Myxtic

0

Nhìn trong /usr/lib/ruby/gems/1.8/gems/activesupport-2.3.8/lib/active_support/json/backends/yaml.rb (phải thừa nhận là một chút khác nhau phiên bản), có vẻ như một ParseError đang được nâng lên. Giả sử các lỗi đang xảy ra tại "format.json", bạn có thể thử một cái gì đó giống như

begin 
    format.json 
rescue ParseError => e 
    render :text => "Now there's some ugly JSON! (#{e.message})", :status => 500 
end 

Nếu điều đó không làm việc, bạn có thể cố gắng bắt nó trước bằng cách sử dụng callback rescue_from trong điều khiển của bạn.

class UsersController < ApplicationController 
... 
    rescue_from ParseError do |e| 
    render ... 
    end 
... 
end 
+0

Cảm ơn bạn đã đề xuất, rất tiếc, lỗi không được nêu ra ở định dạng.json. Tôi tin rằng nó được nâng lên trước khi hành động của người dùng/tạo được gọi vì Rails cần phân tích cú pháp chuỗi JSON để truy cập vào các tham số. – Bob

+0

Ah, tôi đoán là có ý nghĩa. Trong trường hợp đó, hãy thử gọi lại rescue_from. Tôi đã thêm một ví dụ ở trên. – bioneuralnet

+1

Một ý tưởng hay nhưng than ôi, không có súc sắc, lỗi được nâng lên trước khi nó chạm đến bộ điều khiển – Bob

0

Tôi hiện đang gặp sự cố tương tự - Tôi có API để ai đó có thể chuyển JSON không hợp lệ đến và tôi muốn thông minh về lỗi tôi trả về. Tôi đang chạy Rails 3.0.5. Tôi bắt nguồn từ lỗi bị ném tới lib/active_support/json/backends/yaml.rb dòng 17:

def decode(json) 
    if json.respond_to?(:read) 
    json = json.read 
    end 
    YAML.load(convert_json_to_yaml(json)) 
rescue ArgumentError 
    raise ParseError, "Invalid JSON string" 
end 

Vì vậy, json.read thất bại và ném lỗi. Thật không may điều này xảy ra lâu trước khi bộ điều khiển của bạn được gọi ra (đó là một phần của các tham số yêu cầu ban đầu phân tích cú pháp trong đó Rails liên kết với Rack). Tôi sẽ nghĩ rằng để bắt được điều này, bạn cần thêm một con khỉ nhỏ để ghi đè lên một số lỗi được tích hợp và thay vào đó bạn có thể sử dụng ... để có thể thêm tiêu đề vào đối tượng yêu cầu mà sau đó bạn có thể phát hiện trong bộ điều khiển của bạn và ném lỗi của riêng bạn.

Thật không may tôi không nghĩ rằng điều này sẽ làm việc cho tôi vì tôi chỉ muốn ghi đè hành vi khi truy cập API, không phải phần còn lại của trang web. Mặc dù tôi giả sử trong bản vá lỗi khỉ, giả sử tôi có quyền truy cập vào đối tượng yêu cầu, tôi có thể nói rằng chỉ sử dụng hành vi mới của tôi nếu đường dẫn được yêu cầu khớp với regex như /\/api\//

+0

Tôi đã giải quyết vấn đề này bằng cách sử dụng Rack middleware. Phần mềm trung gian được chèn vào trước ActionDispatch :: ParamsParser và bắt các lỗi phát ra bởi @ app.call.Kể từ khi hành động điều khiển cũng là ứng dụng rack trong các ứng dụng đường ray, tôi có thể sử dụng một hành động điều khiển để hiển thị một thông báo lỗi khá bằng cách sử dụng tất cả các đường ray templating. (Đăng cho những người dân khác đến đây từ Google) https://gist.github.com/4709748 –

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