Прежде чем я напишу о том, как добавить фрагментное кэширование, я хотел бы поделиться этим, если люди этого не видели. Я помню, как видел эту технику в коде Рика Олсона некоторое время назад, так что я ему полностью благодарен
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!
метод, который сделал бы этот подход еще чище.