2009-09-03 28 views
13

Khi định tuyến tài nguyên trong Rails, thuộc tính định dạng tùy chọn được tự động nối vào các tuyến được tạo. Điều này là để tài nguyên được đề cập có thể được yêu cầu dưới dạng XML, HTML, vv Các định dạng nào thực sự được cho phép thường được mô tả trong bộ điều khiển bằng cách sử dụng respond_to.Cách giới hạn định dạng tài nguyên trong tệp tuyến đường Rails

Nhưng trong nhiều trường hợp, bạn chỉ muốn hỗ trợ HTML và cảm thấy như một chi phí để viết respond_to :html trong mọi hành động trong mọi bộ điều khiển. Do đó, sẽ rất tuyệt nếu có cách nào giới hạn các loại nội dung được phép khi tạo các tuyến đường trong tệp routes.rb, ví dụ:

map.resources :users, :formats => :html 
map.resources :users, :formats => [:html, :xml] 
map.resources :users, :formats => {:index => :html, :show => [:html, :xml]}

Có cách nào để đạt được điều này hoặc nguồn gốc hoặc thông qua plugin không?

P.S. Cách thông thường để giải quyết vấn đề này là bỏ qua vấn đề và không sử dụng respond_to trong các hành động. Nhưng điều này thực sự không giới hạn các loại nội dung được cho phép. Thay vào đó nó chỉ hy vọng rằng một mẫu tồn tại trong thư mục views cho mỗi kiểu nội dung có thể. Nếu không tồn tại khi được yêu cầu, hệ thống sẽ phát hiện lỗi HTTP 500.

Trả lời

1

Trong cả hai trường hợp, bạn sẽ không muốn lỗi HTTP 500? Giống như trong dòng thứ hai của ví dụ của bạn, nếu ai đó yêu cầu JSON thay vì HTML hoặc XML không phải là mã lỗi trả về phản hồi thích hợp không?

+1

Không, 500 lỗi có nghĩa là một cái gì đó đã đi sai trên máy chủ . Nếu một kiểu nội dung không được hỗ trợ, nó không phải là lỗi máy chủ - đó là lỗi máy khách (máy khách không nên yêu cầu nó). 406 sẽ là mã phản hồi chính xác. Xem "Mã phản hồi HTTP": http://www.sitepoint.com/blogs/2008/02/04/restful-rails-part-i/ –

+0

Chắc chắn nếu bạn định gắn thẻ .xml hoặc .html vào cuối URL và định dạng đó không được hỗ trợ thì bạn không nên tìm thấy 404. Nó có vẻ táo bạo để bỏ qua việc sử dụng conneg bằng cách tạo URL cho từng loại nội dung nhưng sau đó ăn cắp mã repsonse khi không có loại nội dung hợp lệ nào trong tiêu đề chấp nhận! –

+0

Vâng, bạn có thể có một điểm - mặc dù đây thực sự là cách Rails hoạt động ra khỏi hộp. Nhưng tuy nhiên đây không phải là điểm của câu hỏi của tôi. Tôi vẫn muốn xác định điều này ở một vị trí trung tâm (tốt nhất là các tập tin tuyến đường) - không có vấn đề nếu sau đó một 404 hoặc 406 được trả về lỗi –

3

Tôi tin rằng bạn có thể làm một cái gì đó như thế này:

respond_to do |format| 
    format.html 
    format.json { render :json => @things } 
    format.any { render :text => "Invalid format", :status => 403 } 
end 

Nếu người dùng yêu cầu html hoặc JSON nó sẽ làm điều đó như mong muốn, nhưng bất cứ điều gì khác sẽ làm cho "Định dạng không hợp lệ" text.

+0

sẽ hoạt động nhưng tôi nghĩ rằng anh ấy muốn bỏ định dạng: từ các tuyến đường –

0

chứ không phải thực hiện:

def some_action 
    ... 
    respond_to do |format| 
    format.html 
    format.json { whatever } 
    format.any { whatever } 
    end 
end 

chỉ cần sử dụng:

def some_action 
    ... 
end 

và Rails sẽ mặc định tìm kiếm some_action.html.erb hoặc bất cứ định dạng được yêu cầu. Nếu bạn không xác định bất kỳ lượt xem nào khác ngoài html, thì tất cả các định dạng khác sẽ thất bại nếu được yêu cầu.

+0

Tôi nghĩ anh ấy cũng muốn bỏ định dạng: từ các tuyến đường –

5

Vì Rails sử dụng tương đương với ký tự đại diện để xử lý các định dạng ".: Format" hơi khó để ngăn mọi thứ ở phía bên đường.

Thay vì điều này, cách khá dễ dàng để nắm bắt mọi yêu cầu không phải HTML trong bộ lọc trước. Dưới đây là một cách có thể nhìn:

class ApplicationController < ActionController::Base 
    before_filter :check_format 

    private 

    def check_format 
     if request.format != Mime::HTML 
     raise ActionController::RoutingError, "Format #{params[:format].inspect} not supported for #{request.path.inspect}" 
     end 
    end 

end 

ActionController :: RoutingĐược coi là lỗi 404 hợp lý. Trong trường hợp bạn không có một hành động mà cần hỗ trợ một cái gì đó khác hơn là HTML, chỉ cần sử dụng:

skip_before_filter :check_format, :only => ACTION_NAME 
6

Bạn phải quấn những tuyến đường trong một phạm vi nếu bạn muốn hạn chế chúng vào một định dạng cụ thể (ví dụ html hoặc json). Hạn chế không may không hoạt động như mong đợi trong trường hợp này.

Đây là ví dụ về một khối như vậy ...

scope :format => true, :constraints => { :format => 'json' } do 
    get '/bar' => "bar#index_with_json" 
end 

Thông tin thêm có thể được tìm thấy ở đây: https://github.com/rails/rails/issues/5548

Câu trả lời này được sao chép từ câu trả lời trước của tôi ở đây ..

Rails Routes - Limiting the available formats for a resource

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