Skip to content

One Big Fat Example

floere edited this page Sep 13, 2010 · 8 revisions

What is it about?

Think Amazon. It is about a bookstore that shows prices in the user’s currency. Also, it carries books AND toys as items in several views where items are listed. (And toys and books are rendered differently, but have to be able to be in the same list of recommendations for example)

Ok, go.

The following classes all have specs of course ;) But are not shown since they don’t help the example.

ViewModels superclass for this project.

We include all of Rails’ helpers for the view models in this project.
Also, we include the ApplicationHelper.

We delegate logger and current_user calls in the view models to the active controller.

Project superclass for all view models. Includes methods we want all view models to have.


class ViewModels::Project < ViewModels::Base
  
  # Our ApplicationHelper.
  #
  helper ApplicationHelper
  
  # We want to be able to call view_model_for in our view_models.
  #
  helper ViewModels::Helpers::Rails
  
  # Include all common view helpers.
  #
  helper ViewModels::Helpers::View
  
  # We want to be able to use id, dom_id, to_param on the view model.
  #
  # Note: Overrides the standard dom_id method from the RecordIdentificationHelper.
  #
  include ViewModels::Extensions::ActiveRecord
  
  # This delegates any calls to logger and current_user in the view models to the controller.
  #
  controller_method :logger, :current_user
  
end

Item superclass. All items have a price that needs to be displayed according to the current user.


# All items have a description that needs to be filtered by textilize.
#
class ViewModels::Item < ViewModels::Project
  model_reader :description, :filter_through => :textilize
  # Use price in the view as follows:
  # = view_model.price - will display e.g. 16.57 CHF, since it is filtered first through localize_currency
  model_reader :price, :filter_through => :localize_currency
  
  # Converts a database price tag to the users chosen value, with the users preferred currency appended.
  # If the user is Swiss, localize_currency will convert 10 Euros to "16.57 CHF" 
  #
  def localize_currency(price_in_euros)
    converted_price = current_user.convert_price(price_in_euros)
    "#{converted_price} #{current_user.currency.to_s}"
  end
end

Book view model.


# This class also has partial templates in the directory
#   app/views/view_models/book
# that are called
#   _cart_item.html.haml
#   _cart_item.text.erb
#
# Call view_model_for on a book in the view or controller to get this view_model.
#
class ViewModels::Book < ViewModels::Item
  model_reader :author, :title, :pages
  model_reader :excerpt, :filter_through => :textilize
  
  def header
    content_tag(:h1, "#{author} – #{title}")
  end
  
  def full_description
    content_tag(:p, "#{excerpt} #{description}", :class => 'description full')
  end
end

Toy view model.


# This class also has partial templates in the directory
#   app/views/view_models/toy
# that are called
#   _cart_item.html.haml
#   _cart_item.text.erb
#
# Call view_model_for on a toy in the view or controller to get this view_model.
#
class ViewModels::Toy < ViewModels::Item
  model_reader :starting_age, :small_dangerous_parts?
  
  def obligatory_parental_warning
    "Warning, this toy can only be used by kids ages #{starting_age} and up. Your department of health. Thank you."
  end
  
end

Clone this wiki locally