Working with Models
Models
In Rails, the default data structure for a data model is called, naturally enough, a model (the M in MVC) . The default Rails solution to the problem of persistence is to use a database for long-term data storage, and the default library for interacting with the database is called Active Record.1
Active Record comes with a host of methods for creating, saving, and finding data objects, all without having to use the structured query language (SQL) used by relational databases. Moreover, Rails has a feature called migrations to allow data definitions to be written in pure Ruby, without having to learn an SQL data definition language (DDL). The effect is that Rails insulates you almost entirely from the details of the data store.
Create the model
$ script/generate rspec_model User name:string email:string
Migrate “up” using
$ rake db:migrate
Roll back (down) using
$ rake db:rollback
Model annotation
Though it’s not strictly necessary, I like to annotate my Rails models using the annotate models plugin:
$ script/plugin install \ > http://repo.pragprog.com/svn/Public/plugins/annotate_models $ rake annotate_models
This will cause your model files to look like the following:
# == Schema Information # Schema version: # Table name: # id :integer not null, primary key # name :string(255) # email :string(255) # created_at :datetime # updated_at :datetime # class User < ActiveRecord::Base end
After adding any plugins, remember to commit to Git
$ git add . $ git commit -am "Annotated models"
Accessible attributes
Another step that isn’t strictly necessary but is a really good idea is to tell Rails which attributes of the model are accessible, i.e., which attributes can be modified by outside users (such as users submitting requests with web browsers). We do this with the attr accessible method. Using attr accessible is important for preventing a mass assignment vulnerability, a distressingly common and often serious security hole in many Rails applications.
class User < ActiveRecord::Base attr_accessible :name, :email end
Searching models
User.find(1) # where 1 is the User ID
User.find_by_email("david@example.com") # notice the method being called to search for the email.
User.first # finds the first User
User.all # finds all Users and returns them in an array
Two ways to update attributes
user.email = "notDavid@example.com" user.save
or using update_attributes which performs the update and saves in one step. It returns true if the save was successful.
user.update_attributes(:name => "The Guy", :email => "guy@example.com") >> true
Model validations
Add validations to your model files.
class User < ActiveRecord::Base attr_accessible :name, :email validates_presence_of :name end
The database will now not allow save’s to pass if all validations do not pass. Use the valid? method to check if an object passes all validations.
Don’t forget to use table indexes when searching using a database column or ensuring uniqueness.
$ script/generate migration add_email_uniqueness_index
add_index :user, :email, :unique => true