Rails and alternative ORMs
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Rails and alternative ORMs

  • 8,239 views
Uploaded on

Most Rails users are familiar with ActiveRecord. But what does that mean? What is ActiveRecord's approach to object relational mapping? And what are the alternatives?

Most Rails users are familiar with ActiveRecord. But what does that mean? What is ActiveRecord's approach to object relational mapping? And what are the alternatives?

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
8,239
On Slideshare
8,216
From Embeds
23
Number of Embeds
2

Actions

Shares
Downloads
29
Comments
0
Likes
1

Embeds 23

http://www.slideshare.net 21
http://www.slideee.com 2

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • <br /> <br />
  • So ... Why use an ORM? <br />
  • Because your database and your OO code are unlike things. Different paradigms. <br /> <br /> <br /> <br /> So in a sense, any time you use a relational DB + OO, you’re going to do some sort of object relational mapping. <br /> <br /> <br /> <br /> May be formal or informal. <br />
  • <br /> <br />
  • So data types are not identical <br />
  • Your DB has a formal definition independent of the use of the data. <br />
  • This is a big one. <br /> <br /> <br /> <br /> In OO, you follow references - an object can “point” to another object, and so on. <br /> <br /> <br /> <br /> In SQL, you logically join sets of data together. <br />
  • Any bit of data can be joined to any other bit. <br /> <br /> <br /> <br /> In OO, ideal is to hide as much as you can and only expose a public interface. <br />
  • declarative vs. active - declare that certain kinds of data are acceptable, vs. actively checking at certain points in time. <br />
  • SQL doesn’t directly have a concept of inheritance. Fundamental to OO. <br />
  • <br /> <br />
  • Finally, different purposes. <br /> <br /> <br /> <br /> Define structure for data (and hold that data) <br /> <br /> <br /> <br /> vs. <br /> <br /> <br /> <br /> Doing something <br />
  • So basically, ORM are translators between unlike things. Like any translation, <br />
  • this isn’t going to be perfectly smooth, and there will always be tradeoffs. <br /> <br /> <br /> <br /> In this talk, Dan and I are going to talk about these tradeoffs by looking at three approaches to ORM with Ruby. <br />
  • You’re probably familiar with this already, so I won’t show much code here or talk about how to use AR. Instead, let’s talk for a few minutes at a more theoretical level. <br />
  • In this pattern, an object wraps each DB row. This single object handles both domain logic and database access. What's unique about this? <br />
  • Other approaches might not treat each row as an object, or might combine multiple rows into a single object. <br />
  • Others might separate these, filtering the data through a logic layer, instead of exposing both side-by-side. <br />
  • <br /> <br />
  • <br /> <br />
  • class User &lt; ActiveRecord::Base <br /> end <br /> <br /> <br /> <br /> That does a _lot_. And from looking at this, you have no idea exactly what it did. You have to check the db schema in order to figure that out. <br /> <br /> <br /> <br /> The good news is that convention dominates. Once you know the conventions, you generally aren't surprised. <br />
  • This is true, by default. N+1, loads all columns, etc. <br /> <br /> <br /> <br /> It would be really nice if it could do these things. <br /> <br /> <br /> <br /> But at the same time, it provides facilities for these sorts of optimizations. <br /> <br /> <br />
  • This is part of the reason that alternative ORMs got started. <br /> <br /> <br /> <br /> The thing is, it isn't true any more. At least not entirely. <br /> <br /> <br />
  • This guy, Josh Peek, made Rails 2.2 thread safe. <br />
  • And this guy, who you may recognize, added the current connection pooling. <br />
  • The fact is, as a AR developer, you can pretty much forget how to write a join. <br /> <br /> <br /> <br /> This isn't really a limitation of AR - some could say that it’s a feature. But at the same time, you really do need to know SQL if you’re going to use a relational database. <br /> <br /> <br /> <br /> That said, my SQL skills have atrophied as a Rails developer. On our newest project, Luke and I have had to do quite a bit of custom SQL, and we've tried to make our DB layer a bit smarter and more robust. Which leads to the next criticism... <br /> <br /> <br />
  • Rails makes polymorphic associations easy and multi-table inheritance hard. <br /> <br /> <br /> <br /> But polymorphic associations: bad idea. Cuts out a join table, but hurts referential integrity. But because it’s easy, you see a lot of it. <br /> <br /> <br /> <br /> Is this a valid criticism? It usually isn’t that hard to fight against AR’s conventions, and most of the time, you don’t want to. <br />
  • This is bad. Basically, foreign keys require a plugin. Redhill. This plugin works, but isn't all that actively maintained, and some things (constraints) aren't even supported by that. <br /> <br /> <br /> <br /> You can always run a bare connection.execute() statement, but this won't get dumped into your schema.rb file, which is bad. <br /> <br /> <br /> <br /> According to DHH et al, you don't need DB constraints, and you want a dumb DB. <br /> <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • 4. Access your database directly. <br />
  • <br /> <br />
  • Company 1 may not exist. <br /> <br /> <br /> <br /> Or <br />
  • <br /> <br />
  • I.e. you make a mistake <br />
  • I.e. you make a mistake. <br /> <br /> <br /> <br /> This probably isn’t a problem for you, but it might be for some of the other people you work with. <br />
  • Sequel is a thread-safe DB library with a lightweight ORM <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br />
  • Follows the ActiveRecord pattern <br />
  • So you don’t have to write much real SQL <br />
  • So you don’t have to write much real SQL <br />
  • The Sequel ORM is very similar to AR, at least on the surface. <br /> <br /> <br /> <br /> Does many of the things that Rails does, at least the basics. <br />
  • <br /> <br />
  • <br /> <br />
  • Also has similar support for sharding <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />

Transcript

  • 1. Rails and Alternative ORMs Dan Weinand Jonathan Dahl
  • 2. Why?
  • 3. DB vs. OO declarative vs. imperative
  • 4. DB vs. OO char/text vs. string
  • 5. DB vs. OO schema vs. _______
  • 6. DB vs. OO joins vs. pointers
  • 7. DB vs. OO public vs. encapsulated
  • 8. DB vs. OO constraints vs. validation
  • 9. DB vs. OO _____ vs. inheritance
  • 10. DB vs. OO DBA vs. programmer
  • 11. DB vs. OO structure vs. behavior
  • 12. http://www.engrish.com//wp-content/uploads/2008/08/hand-grenade.jpg
  • 13. 1. ActiveRecord
  • 14. An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data. Martin Fowler, PoEAA, 160.
  • 15. One object per row.
  • 16. Data access and domain logic are done together.
  • 17. 6 Criticisms of ActiveRecord
  • 18. 1. Too much magic. http://cgi.ebay.com/MEDIEVAL-MAGE-KING-BLACK-TUNIC-COSTUME-SCA-LARP-_W0QQitemZ250373576829QQcmdZViewItemQQimsxZ20090215?IMSfp=TL090215143008r8810#ebayphotohosting
  • 19. class User < ActiveRecord::Base end
  • 20. 2. Not performant. http://www.flickr.com/photos/danprates/1418154518/
  • 21. 3. Not thread safe. No connection pooling. http://www.flickr.com/photos/streetmuseo/57990915/
  • 22. 4. Hides SQL from you. http://www.momentaryfascinations.com/entertainment/the.lost.monty.python.cartoon/still.5.jpg
  • 23. 5. Hard to fight against. http://www.mmonotebook.com/wp-content/uploads/2008/04/larp.jpg
  • 24. 6. Encourages stupid databases.
  • 25. 9 ways to bypass application-level constraints
  • 26. 1. Fixtures
  • 27. 2. Klass.delete(1)
  • 28. 3. record.save(false)
  • 29. 4.
  • 30. 5. Share DB with a second app
  • 31. 6. User.create(:company_id => 1)
  • 32. class User < ActiveRecord::Base 7. has_many :posts end
  • 33. 8. ActiveRecord::Base.connection.execute()
  • 34. 9. Errors in your app logic
  • 35. 2. Sequel
  • 36. An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data. Martin Fowler, PoEAA, 160.
  • 37. Ruby DSL for SQL posts = DB[:posts] posts.filter(:category => /ruby/i, :author => [:jon, :dan]) posts.reverse_order(:created_at, :updated_at) posts.select(:title, :author) posts.limit(10)
  • 38. Ruby-like DSL for SQL posts.filter(:category => :ruby).order(:created_at).select(:title, :author)
  • 39. ORM class Post < Sequel::Model many_to_many :tags many_to_one :author validates_presence_of :title end post = Post[123] post.title # quot;rails ormsquot; post.title = quot;Rails ORMsquot; post.save
  • 40. 3 interesting things sequel postgres://localhost:5432/myapp_development
  • 41. 3 interesting things require 'memcache' CACHE = MemCache.new 'localhost:11211', :namespace => 'blog' class Author < Sequel::Model set_cache CACHE, :ttl => 3600 end Author[333] # database hit Author[333] # cache hit
  • 42. 3 interesting things DB = Sequel.sqlite('app_test.db', :servers=>{:read_only=>{:host=>'slave_server'}})
  • 43. 3. Datamapper
  • 44. A layer of Mappers (473) that moves data between objects and a database while keeping them independent of each other and the mapper itself. Martin Fowler, PoEAA, 165.
  • 45. Multiple Databases • SQL-based • In-memory • Document-based • Search engines
  • 46. Explicit property mapping class Message include DataMapper::Resource property :name, String property :body, Text property :created_at, DateTime validates_presence_of :name end
  • 47. Get only the data you need
  • 48. Minimize the number of queries
  • 49. Save only the data that has changed
  • 50. Identity Map repository do @parent.children.each do |child| puts @parent.object_id = child.parent.object_id end end
  • 51. Ruby Query Syntax Zoo.first(:name.eql => 'Galveston') Person.all(:age.gt => 30) Person.all(:age.gte => 30) Person.all(:name.not => 'bob') Person.all(:name.like => 'S%', :id => [1,2,3,4,5]) Person.all(:name.not => ['bob','rick','steve']) Person.all(:order => [:age.desc])
  • 52. Chainable finders class Zoo def self.open all(:open => true) end def self.big all(:animal_count.gte => 1000) end end big_open_zoos = Zoo.big.open
  • 53. Associations class Article include DataMapper::Resource property :id, Serial property :title, String property :content, Text belongs_to :author end class Author include DataMapper::Resource property :id, Serial property :name, String has n, :articles end Article.all('author.name' => 'Michael')
  • 54. Implicit and explicit migrations
  • 55. Only basic functionality in core
  • 56. Gems for everything else
  • 57. Is it ready for primetime?
  • 58. Roadmap to 1.0
  • 59. Rails integration still lacking
  • 60. Not many production deployments
  • 61. Documentation sucks
  • 62. Some plugins still not ported
  • 63. Thanks! Dan Weinand Jon Dahl