Add your own rich type
Originally written by Tom on 2008-10-16.
Say your application features currency value, and you’d like them all formatted nicely. A great way to implement this in Hobo is by creating a new type, e.g.
Dollars and customising the way those values are displayed. That way your dollar values will be displayed correctly throughout the site and you won’t need to think about that issue again.
Start with a blank app
To make this how-to very concrete let’s start from scratch with a new application:
$ hobo my_app $ cd my_app $ ./script/generate hobo_model_resource product name:string
Create the type
Now we’ll dive right in and create the new type. Create
app/models/dollars.rb like this:
class Dollars < DelegateClass(BigDecimal) COLUMN_TYPE = :decimal end
Let’s talk that through. It’s common with Rich types to create a new subclass of the ‘normal’ type that ActiveRecord would use. For example, Hobo’s
HtmlString is a subclass of
String. Unfortunately, subclassing
BigDecimal is problematic for reasons we won’t bother going in to. Fortunately Ruby saves us with the very nifty
DelegateClass. This allows us to walk like a
BigDecimal and talk like a
BigDecimal, which is perfectly good enough in Ruby.
We then declare
COLUMN_TYPE = :decimal
which tells the migration generator what type of column to generate for these things. That’s arguably redundant seeing as we already defined these things as being a special kind of
BigDecimal. This step might go away in the future.
To render these dollar values nicely in the app, we need to define a custom <view> tag. So in application.dryml we need:
<def tag="view" for="Dollars">$<%= number_to_currency(this) %></def>
Declare a field with the custom type
Now our type is ready to go. We can edit
app/modes/product.rb like this:
class Product < ActiveRecord::Base hobo_model fields do name :string price Dollars, :precision => 12, :scale => 2 timestamps end ... end
Notice the type of the
price column is given as the class constant
Dollars. We can pass the same options that we could to a regular
Create the database
If we now run the migration geneartor:
$ ./script/generate hobo_migration
You’ll see that the price column is
:decimal type (the users table has been omitted for brevity):
---------- Up Migration ---------- create_table :products do |t| t.string :name t.decimal :price, :scale => 2, :precision => 12 t.datetime :created_at t.datetime :updated_at end ---------------------------------- ---------- Down Migration -------- drop_table :products ----------------------------------
Try it out
That’s it! You can now fire up the app and sign up to become the administrator. Create a product with a price, and see the nice dollar formatting.
Bonus - a custom input for dollars
Add this to
<def tag="input" for="Dollars" attrs="name"> $ <%= text_field_tag(name, this, attributes) %> </def>
You’ll now have a dollar sign in front of every dollar field in your forms.
Edit this page