Inspired by Active Record, Objectify is a Ruby object-relational mapping (ORM) library, which uses SQLite3 as its database. Objectify provides an SQLObject
base class. When users define a new class (model) that is a subclass of SQLObject
, a mapping between the model and an existing table in the database is established. Moreover, models can connect with other models by defining associations.
For demo purposes, a database geo.db
is provided. To experience Objectify, run the following commands in your terminal:
git clone https://github.com/davidfeng88/Objectify.git
cd Objectify/
irb
load 'geo.rb'
- Try the following commands!
# all
City.all
# => [#<City:0x00007fa4fd09f5c0 @attributes={:id=>1, :name=>"Beijing", :country_id=>1}>, ...]
# find
Country.find(3)
# => #<Country:0x00007fa4fc1bca58 @attributes={:id=>3, :name=>"United States", :continent_id=>2}>
# first, last, associations
beijing = City.first
# => #<City:0x00007fa4fc2e6af0 @attributes={:id=>1, :name=>"Beijing", :country_id=>1}>
beijing.country
# => #<Country:0x00007fa4fd14f4c0 @attributes={:id=>1, :name=>"China", :continent_id=>1}>
beijing.continent
# => #<Continent:0x00007fa4fd14c068 @attributes={:id=>1, :name=>"Asia"}>
canada = Country.last
# => #<Country:0x00007fa4fc19c118 @attributes={:id=>4, :name=>"Canada", :continent_id=>2}>
canada.continent
# => #<Continent:0x00007fa4fd15cd50 @attributes={:id=>2, :name=>"North America"}>
# where
japan = Country.where(name: "Japan").first
# => #<Country:0x00007fa4fc122660 @attributes={:id=>2, :name=>"Japan", :continent_id=>1}>
kyoto = City.new(name: "kyoto", country_id: japan.id)
# => #<City:0x00007fa4fc2e4188 @attributes={:name=>"kyoto", :country_id=>2}>
kyoto.save
# => 8
City.last
# => #<City:0x00007fa4fd13f930 @attributes={:id=>8, :name=>"kyoto", :country_id=>2}>
kyoto.name = "Kyoto"
# => "Kyoto"
kyoto.save
# => []
City.last
# name updated!
# => #<City:0x00007fa4fd12ec20 @attributes={:id=>8, :name=>"Kyoto", :country_id=>2}>
Note: Check out geo.sql
file for the content of the demo database.
-
::all
returns an array of all instances of the class. -
::first
and::last
return first and last instance of the class respectively. -
::find(id)
returns the instance with the id provided. It returnsnil
if not found. -
::new(params)
creates a new instance with an optional hash of parameters. -
#save
saves the changes of the instance in the database. It calls#insert
or#update
based on whether the id isnil
or not.
-
::columns
returns an array of column names (symbols). -
::table_name
and::table_name=
: table name getter and setter methods.
::where(params)
takes in a hash of parameters. It returns an empty array if nothing is found. For example:
Country.where(name: "Japan") # => an array of Country instances where the name is "Japan"
- Associations are defined in the
.rb
file before::finalize!
. For example:
class Continent < SQLObject
has_many :countries
finalize!
end
class Country < SQLObject
belongs_to :continent
finalize!
end
-
Supported associations currently include
has_many
,belongs_to
,has_one_through
. -
has_many
andbelongs_to
takes a required name and an optional hash forclass_name
,primary_key
, andforeign_key
. -
has_one_through
requires three arguments:name
,through_name
,source_name
.has_one_through
connects twobelongs_to
associations. For example, in the demo database:City
has abelongs_to
association (:country
) withCountry
Country
has abelongs_to
association (:continent
) withContinent
- I defined a
has_one_through
association (:continent
) forCity
using the following options:name
::continent
through_name
::country
source_name
::continent
You need to create three files (.sql
, .db
, and .rb
) as follows. Refer to geo.sql
and geo.rb
files if needed.
- Write a SQL source file (
.sql
). - Run
cat FILENAME.sql | sqlite3 FILENAME.db
to generates the database file (.db
). - Edit the
SQL_FILE
andDB_FILE
constants in/lib/db_connection.rb
so that they point to the.sql
and.db
files in step 1 and 2. - Write a Ruby file (
.rb
) to define the models and set up the associations. - In
irb
orpry
, load the.rb
file and you are good to go!
- Write
where
so that it is lazy and stackable. Implement aRelation
class. - Validation methods/validator class.
has_many :through
- This should handle both
belongs_to => has_many
andhas_many => belongs_to
.
- This should handle both
- Write an
includes
method that does pre-fetching. joins