#!/usr/bin/env ruby ENV['LOG_NAME'] ||= 'example' require 'environment' # Define a fixtures helper method to load up our test data. def fixtures(name) entry = YAML::load_file(File.dirname(__FILE__) + "/spec/fixtures/#{name}.yaml") klass = begin Kernel::const_get(Inflector.classify(Inflector.singularize(name))) rescue nil end unless klass.nil? database.logger.debug { "AUTOMIGRATE: #{klass}" } klass.auto_migrate! (entry.kind_of?(Array) ? entry : [entry]).each do |hash| if hash['type'] Object::const_get(hash['type'])::create(hash) else klass::create(hash) end end else table = database.table(name.to_s) table.create! true table.activate_associations! #pp database.schema (entry.kind_of?(Array) ? entry : [entry]).each do |hash| table.insert(hash) end end end # Pre-fill the database so non-destructive tests don't need to reload fixtures. Dir[File.dirname(__FILE__) + "/spec/fixtures/*.yaml"].each do |path| fixtures(File::basename(path).sub(/\.yaml$/, '')) end require 'irb' # database { IRB::start } IRB::start if false # Simple example to setup a database: DataMapper::Database.setup({ :adapter => 'mysql', :database => 'data_mapper_1', :username => 'root' }) class Animal #:nodoc: include DataMapper::Persistence set_table_name 'animals' # Just as an example. Same inflector as Rails, # so this really isn't necessary. property :name, :string property :notes, :string, :lazy => true has_and_belongs_to_many :exhibits end class Exhibit #:nodoc: include DataMapper::Persistence property :name, :string belongs_to :zoo end class Zoo #:nodoc: include DataMapper::Persistence property :name, :string has_many :exhibits end class Person #:nodoc: include DataMapper::Persistence property :name, :string property :age, :integer property :occupation, :string property :notes, :text, :lazy => true # Generates Person::Address class: embed :address do property :street, :string property :city, :string property :state, :string, :size => 2 property :postal_code, :string end end # Compatible with ActiveRecord finder syntax: Zoo.find(1) Zoo.find(:first, :conditions => ['name = ?', 'Galveston']) Zoo.find(:all) # These are options as well: Zoo[1] Zoo.first(:name => 'Galveston') Zoo.all # Or even this as an alias to ::first: Zoo[:name => 'Galveston'] # EmbeddedValues are just nice sugar to partition # denormalized data. Person.first.address.city # Remove all data in a table... Person.truncate! # Create a new object... Person::create(:name => 'Sam', :age => 30, :occupation => 'Software Monkey') # Saving only updates the values that have changed, # and is skipped entirely if the object is not dirty. dumbo = Animal.first(:name => 'Elephant') dumbo.notes = 'He can fly!' dumbo.save # returns true dumbo.save # The object is no longer dirty, so returns false # DataMapper associations are loaded as sets. # Here's the code: Zoo.all.each { |zoo| zoo.exhibits.entries } # The important bit to understand about the above is that # every Zoo that was loaded by Zoo.all has a reference to # every other Zoo it was loaded with through Zoo#loaded_set. # This is then used to load all other instances in the set # when the association of one instance is accessed. So while # it looks like we'd run into the dreaded 1+N query problem # with the above, we actually avoid it entirely. The above # code will only execute two queries. The first to find all # zoos, the second to load all exhibits with zoo_id's that # are a part of the set of loaded zoos. # Objects within the same session are uniqued, so this is both # faster, and fulfills obvious expectations. database do Zoo.first == Zoo.first end # DataMapper find_by_sql equivilent database.query("SELECT * FROM zoos") end