Статьи

Быть хорошим маленьким 404er

Прежде чем я напишу о том, как добавить фрагментное кэширование, я хотел бы поделиться этим, если люди этого не видели. Я помню, как видел эту технику в коде Рика Олсона некоторое время назад, так что я ему полностью благодарен

ActiveRecord вызывает исключение RecordNotFound если не может найти запись базы данных с запрошенным идентификатором.

 def show @person = Person.find(params[:id]) end 

Если params[:id] не соответствует записи в базе данных, будет ActiveRecord::NotFound исключение ActiveRecord::NotFound . Используя метод Rescue_action_in_public от rescue_action_in_public мы можем зафиксировать эти исключения и выбросить 404 соответственно, и, по крайней мере, для меня это охватывает около 99% случаев использования.

Чтобы сделать это приложение широко, добавьте следующий защищенный метод в ваш ApplicationController.rb

 def rescue_action_in_public(e) if e.is_a? ActiveRecord::RecordNotFound render :file => "#{RAILS_ROOT}/public/404.html", :status => '404 Not Found' else super end end 

В действительности я обычно перемещаю этот вызов render в метод render_404 , чтобы вы могли обрабатывать HTML, XML и любые другие типы запросов. Это также позволяет вам вызывать его из подклассов контроллера, если это необходимо.

 def render_404 respond_to do |format| format.html { render :file => "#{RAILS_ROOT}/public/404.html", :status => '404 Not Found' } format.xml { render :nothing => true, :status => '404 Not Found' } end true end def rescue_action_in_public(e) case e when ActiveRecord::RecordNotFound render_404 else super end end 

Чтобы быть хорошим маленьким 404er с приведенным выше кодом, все, что вам нужно сделать, это убедиться, что ваши важные вызовы базы данных выдают это исключение, что подводит меня к важному моменту: в Rails 1.1 единственным типом find который вызывает исключение RecordNotFound является поиск по идентификатору (прочитайте первый абзац документации по методу find ). Если вы делаете поиск другого типа, вы должны справиться с этим самостоятельно:

 def show @tag = Tag.find_by_name(params[:name]) or raise ActiveRecord::RecordNotFound end 

То же самое относится (то есть вызывает ваше собственное исключение) с find(:all) и find(:first) а также.

Если вы хотите бросить 404 напрямую, вы можете просто сделать:

 def show @tag = Tag.find_by_name(params[:name]) or (render_404 and return) end 

В списке rails-core обсуждается добавление find! метод, который сделал бы этот подход еще чище.