test/hobofields_api.rdoctest in hobofields-0.7.5 vs test/hobofields_api.rdoctest in hobofields-0.8
- old
+ new
@@ -7,10 +7,11 @@
>> require 'rubygems'
>> require 'activesupport'
>> Dependencies.load_paths << '.'
>> Dependencies.mechanism = :require
>> require 'activerecord'
+ >> require 'action_controller'
>> require 'hobofields'
>> mysql_database = "hobofields_doctest"
>> system("mysqladmin create #{mysql_database}") or raise "could not create database"
>> ActiveRecord::Base.establish_connection(:adapter => "mysql",
:database => mysql_database,
@@ -33,11 +34,11 @@
The migration generator uses this information to create a migration. The following creates and runs the migration so we're ready to go.
>> up, down = HoboFields::MigrationGenerator.run
>> ActiveRecord::Migration.class_eval up
-
+
We're now ready to start demonstrating the API
## The Basics
The main feature of HoboFields, aside from the migration generator, is the ability to declare rich types for your fields. For example, you can declare that a field is an email address, and the field will be automatically validated for correct email address syntax.
@@ -47,47 +48,47 @@
Field values are returned as the type you specify.
>> a = Advert.new :body => "This is the body"
>> a.body.class
=> HoboFields::Text
-
+
This also works after a round-trip to the database
>> a.save
>> b = Advert.find(a.id)
>> b.body.class
=> HoboFields::Text
-HoboFields::Text is a simple subclass of string. It's a "wrapper type", by which we mean you pass the underlying value to the constructor.
+HoboFields::Text is a simple subclass of string. It's a "wrapper type", by which we mean you pass the underlying value to the constructor.
>> t = HoboFields::Text.new("hello")
=> "hello"
>> t.class
=> HoboFields::Text
-
+
If you define your own rich types, they need to support a one argument constructor in the same way.
Although the body of our advert is really just a string, it's very useful that it has a different type. For example, the view layer in Hobo Rapid would use this information to render a `<textarea>` rather than an `<input type='text'>` in an Advert form.
-
+
## Names vs. Classes
In the `fields do ... end` block you can give the field-type either as a name (symbol) or a class. For example, we could have said
body HoboFields::Text
-
+
Obviously the symbol form is a nicer:
body :text
-If you provide a class it must define the `COLUMN_TYPE` constant. This instructs the migration generator to create the appropriate underlying database column type. It should be a symbol that is a valid column type in a Rails migration.
+If you provide a class it must define the `COLUMN_TYPE` constant. This instructs the migration generator to create the appropriate underlying database column type. It should be a symbol that is a valid column type in a Rails migration.
>> HoboFields::Text::COLUMN_TYPE
=> :text
-
+
The full set of available symbolic names is
-
+
* `:integer`
* `:big_integer`
* `:float`
* `:string`
* `:text`
@@ -102,22 +103,22 @@
You can add your own types too. More on that later.
## Model extensions
-
+
HoboFields adds a few features to your models.
-
+
### `Model.attr_type`
Returns the type (i.e. class) declared for a given field or attribute
>> Advert.attr_type :title
=> String
>> Advert.attr_type :body
=> HoboFields::Text
-
+
### `Model.column`
A shorthand for accessing column metadata
>> col = Advert.column :title
@@ -134,23 +135,23 @@
class Advert
attr_accessor :my_attr, :type => :text
end
>> a = Advert.new
>> a.my_attr = "hello"
- >> a.my_attr.class
+ >> a.my_attr.class
=> HoboFields::Text
-
+
## Field validations
HoboFields gives you some shorthands for declaring some common validations right in the field declaration
### Required fields
The `:required` argument to a field gives a `validates_presence_of`:
- >>
+ >>
class Advert
fields do
title :string, :required
end
end
@@ -160,17 +161,17 @@
>> a.errors.full_messages
=> ["Title can't be blank"]
>> a.title = "Jimbo"
>> a.save
=> true
-
+
### Unique fields
The `:unique` argument in a field declaration gives `validates_uniqueness_of`:
-
- >>
+
+ >>
class Advert < ActiveRecord::Base
fields do
title :string, :unique
end
end
@@ -180,55 +181,55 @@
>> a.errors.full_messages
=> ["Title has already been taken"]
>> a.title = "Sambo"
>> a.save
=> true
-
+
Let's get back to the basic Advert class with no validations before we continue:
-
+
>> Dependencies.remove_constant "Advert"
>>
class Advert < ActiveRecord::Base
fields do
title :string
body :text
contact_address :email_address
end
end
-
+
### Type specific validations
Rich types can define there own validations by a `#validate` method. It should return an error message if the value is invalid, otherwise nil. We can call that method directly to show how it works:
>> a = Advert.new :contact_address => "not really an email address"
>> a.contact_address.class
=> HoboFields::EmailAddress
>> a.contact_address.validate
=> "is not valid"
-
+
But normally that method would be called for us during validation:
-
+
>> a.valid?
=> false
>> a.errors.full_messages
=> ["Contact address is not valid"]
>> a.contact_address = "me@me.com"
>> a.valid?
=> true
-
+
You can add this capability to your own rich types just by defining `#validate`
-
+
### Validating virtual fields
You can set the type of a virtual field to a rich type, e.g.
>>
class Advert
attr_accessor :alternative_email, :type => :email_address
end
-
+
By default, virtual fields are not subject to validation.
>> a = Advert.new :alternative_email => "woot!"
>> a.valid?
=> true
@@ -239,9 +240,9 @@
class Advert
validate_virtual_field :alternative_email
end
>> a.valid?
=> false
-
+
## Cleanup
>> system "mysqladmin --force drop #{mysql_database}"