-
Notifications
You must be signed in to change notification settings - Fork 2
Error Handling
dburry edited this page Jul 15, 2012
·
17 revisions
Here is an example of using full error handling in your app. This method uses a table-less activerecord class to handle validations for the search form.
# app/models/search_form.rb
class SearchForm
# table-less model
# someday include ActiveModel::Model may simplify this...
include ActiveModel::Validations
def initialize(params={})
params.each { |atr, val| send("#{atr}=", val) } if params
end
def persisted?
false
end
def to_key
nil
end
# set up attrs and defaults
attr_accessor :query, :page
def page
@page.blank? ? '1' : @page
end
# validation of attrs
validates_presence_of :query
validate do
if query.present? && ! results?
errors.add :query, errors.generate_message(:query, :not_found)
end
end
validates_numericality_of :page, :only_integer => true,
:greater_than_or_equal_to => 1,
:less_than_or_equal_to => proc { |search_form| search_form.maximum_page },
:if => proc { |search_form| search_form.query.present? }
# shortcuts for accessing info about the searches query
include IndexedSearchHelper
PAGE_SIZE = 10
def maximum_page
# total_pages comes from IndexedSearchHelper
results? ? total_pages(PAGE_SIZE, count) : 1
end
def results
@results ||= IndexedSearch::Entry.find_results(parsed_query, PAGE_SIZE, page.to_i)
end
def count
@count ||= query.blank? ? 0 : IndexedSearch::Entry.count_results(parsed_query)
end
def results?
count > 0
end
def parsed_query
@parsed_query ||= IndexedSearch::Query.new(query)
end
end
# config/routes.rb
Foo::Application.routes.draw do
resource :search
# plus resources for the models you've defined to be searchable!
end
# app/controllers/searches_controller.rb
class SearchesController < ApplicationController
def show
@search_form = SearchForm.new(params[:search_form])
end
end
<!-- app/views/searches/show.erb -->
<%= form_for @search_form, :url => search_path, :method => :get, :authenticity_token => false do |search_form| %>
<%= search_form.text_field :query %>
<%= search_form.hidden_field :page %>
<%= search_form.submit %>
<% end %>
<% if ! @search_form.valid? %>
<% @search_form.errors.full_messages.each do |message| %>
<div><%= message %></div>
<% end %>
<% elsif @search_form.results? %>
<% @search_form.results.each do |result| %>
<!-- assumes every model has a name attribute to display here -->
<div><%= link_to result.model.name, result.model %></div>
<% end %>
<% end %>
# config/locales/en.yml
en:
helpers:
submit:
search_form:
create: Go!
activemodel:
errors:
models:
search_form:
attributes:
query:
blank: must be entered
not_found: not found, try again
page:
not_a_number: must be a number
not_an_integer: must be an integer
greater_than_or_equal_to: must be greater than or equal to %{count}
less_than_or_equal_to: must be less than or equal to %{count}
You might notice it includes validation and error reporting for a page number, yet doesn’t include any fancy page navigation in the view… We’ll leave that for a different exercise. :)