DataMapper @ RubyEnRails2009

4,634 views

Published on

An overview of what DataMapper can do and where it will go in the future

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,634
On SlideShare
0
From Embeds
0
Number of Embeds
300
Actions
Shares
0
Downloads
29
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

DataMapper @ RubyEnRails2009

  1. 1. Dirkjan Bussink http://github.com/dbussink http://twitter.com/dbussink
  2. 2. ORM?
  3. 3. DataMapper 0.10 is Released DataMapper 0.10 is ready for release. We’ve worked on it for the past 11 months, pushed 1250 commits, written 3000+ specs, and fixed 140 tickets in the process.
  4. 4. 1.8 1.9 JRuby Windows * * Sorry, no Windows / 1.9 yet...
  5. 5. Dan Kubb
  6. 6. DataMapper 101
  7. 7. class Person include DataMapper::Resource property :id, Serial property :name, String property :age, Integer end
  8. 8. DataMapper.auto_migrate! DataMapper.auto_upgrade!
  9. 9. class Person ... property :name, String, :length => 512 ... end
  10. 10. Person.all(:name.like => "%me%") Ruby!
  11. 11. repository do puts Person.get(1).object_id => 2232427080 puts Person.get(1).object_id => 2232427080 end Identity Map
  12. 12. Pluggable Identity Map
  13. 13. http://www.flickr.com/photos/mattimattila
  14. 14. people = Person.all(:name.like => "%me%") ~ Query log empty... p people ~ SELECT "id", "name" FROM people
  15. 15. :each Kicker
  16. 16. people = Person.all people.each do |person| p person.addresses end SELECT "id", "name" FROM people; SELECT "id", "street" FROM addresses WHERE ("person_id" IN (1,2,3)) Eager loading
  17. 17. RDBMS IMAP YAML
  18. 18. DataMapper.setup(:repo1, "postgres://postgres@localhost/dm") DataMapper.setup(:repo2, "mysql://root@localhost/dm") repository(:repo1) do p Person.get(1) => #<Person @id=1 @name="Dirkjan" @age=27> end repository(:repo2) do p Person.get(1) => #<Person @id=1 @name="Dan" @age=35> end Multiple repositories
  19. 19. DataMapper.setup(:repo1, "postgres://postgres@localhost/dm") DataMapper.setup(:repo2, "mysql://root@localhost/dm") get "/" do # Odd / even sharding repo = "repo#{user.id % 2 + 1}".to_sym repository(repo) do @people = Person.all end erb :people end Simple sharding
  20. 20. module DataMapper module Adapters class MyStorageAdapter < AbstractAdapter def create(resources) end def read(query) end def update(attributes, collection) end def delete(collection) end end end end
  21. 21. Person.all(:name.like => 'dirk%').update!(:age => 28) Person.all.destroy!(:age.gte => 100) Bulk updates
  22. 22. When simple querying is not enough
  23. 23. Person.all(Person.addresses.street.like => "%street%") SELECT "people"."id", "people"."name", "people"."age" FROM "people" INNER JOIN "addresses" ON "people"."id" = "addresses"."person_id" WHERE "addresses"."street" LIKE '%street%' GROUP BY "people"."id", "people"."name", "people"."age" ORDER BY "people"."id" Complex querying!
  24. 24. class Person include DataMapper::Resource property :id, Serial property :name, String property :age, Integer has n, :addresses def self.named_like_me all(:name.like => "%me%") end def self.older_than_me all(:age.gt => 27) end end Person.named_like_me.older_than_me ~ SELECT "id", "name", "age" FROM "people" WHERE ("name" LIKE '%me%' AND "age" > 27) ORDER BY "id" Query chaining
  25. 25. class Person s include DataMapper::Resource e property :id, Serial p property :name, String o y property :age, Integer c b s u has n, :addresses d R def self.named_like_me e all(:name.like => "%me%") end m in a la def self.older_than_me all(:age.gt => 27) N p end end i n Person.named_like_me.older_than_me ~ SELECT "id", "name", "age" FROM "people" WHERE ("name" LIKE '%me%' AND "age" > 27) ORDER BY "id" Query chaining
  26. 26. Person.all(:name.like => '%me%').addresses.all(:street.not => nil) SELECT "id", "street", "person_id" FROM "addresses" WHERE ( "person_id" IN (SELECT "id" FROM "people" WHERE "name" LIKE '%me%') AND "street" IS NOT NULL ) ORDER BY "id" Subqueries
  27. 27. Person.all - Person.all(:name => 'Dan Kubb') SELECT * FROM people WHERE NOT(name = 'Dan Kubb')
  28. 28. [1, 2] & [2, 3] == [2] [1, 2] | [2, 3] == [1, 2, 3]
  29. 29. Plugins
  30. 30. class Person ... property :name, String, :nullable => false end CREATE TABLE "people" ("id" SERIAL NOT NULL, "name" VARCHAR(50) NOT NULL, "age" INTEGER, PRIMARY KEY("id")) Automatic Validations
  31. 31. Person.create DataObjects::IntegrityError: ERROR: null value in column "name" violates not-null constraint
  32. 32. person = Person.create p person.errors => #<DataMapper::Validate::ValidationErrors:0x101d217a0 @errors={:name=>["Name must not be blank"]}, @resource=#<Person @id=nil @name=nil @age=nil>>
  33. 33. class Person ... validates_present :name end Validations
  34. 34. class Person ... property :created_at, DateTime property :updated_at, DateTime end Timestamps
  35. 35. Person.all.adjust!(:age => 1) Adjustments
  36. 36. class Person ... has n, :addresses, :constraint => :destroy! end ALTER TABLE addresses ADD CONSTRAINT addresses_person_id_fk FOREIGN KEY (person_id) REFERENCES people ON DELETE CASCADE ON UPDATE CASCADE Constraints
  37. 37. module DataMapper module Types class IPAddress < DataMapper::Type primitive String length 16 def self.load(value, property) IPAddr.new(value) end def self.dump(value, property) value.to_s end def self.typecast(value, property) value.kind_of?(IPAddr) ? value : load(value, property) end end end end class NetworkNode ... property :ipaddress, IPAddress end Custom types
  38. 38. class Address include DataMapper::EmbeddedValue property :street, String end class Person include DataMapper::Resource property :id, Serial property :name, String has n, :addresses end
  39. 39. User.select { |u| u.id == 1 && u.name == 'Dan Kubb' } Ambition style queries
  40. 40. http://www.flickr.com/photos/zoomar
  41. 41. http://datamapper.org/ http://github.com/datamapper http://groups.google.com/group/datamapper irc://irc.freenode.net/#datamapper
  42. 42. Questions?

×