Your SlideShare is downloading. ×
0
Rails and Alternative
        ORMs
       Dan Weinand
       Jonathan Dahl
Why?
DB vs. OO

declarative vs. imperative
DB vs. OO

char/text vs. string
DB vs. OO

schema vs. _______
DB vs. OO

joins vs. pointers
DB vs. OO

public vs. encapsulated
DB vs. OO

constraints vs. validation
DB vs. OO

_____ vs. inheritance
DB vs. OO

DBA vs. programmer
DB vs. OO

structure vs. behavior
http://www.engrish.com//wp-content/uploads/2008/08/hand-grenade.jpg
1. ActiveRecord
An object that wraps a row in a database table or view,
encapsulates the database access, and adds domain logic on
that da...
One object per row.
Data access and domain
logic are done together.
6 Criticisms
of ActiveRecord
1. Too much magic.




http://cgi.ebay.com/MEDIEVAL-MAGE-KING-BLACK-TUNIC-COSTUME-SCA-LARP-_W0QQitemZ250373576829QQcmdZVie...
class User < ActiveRecord::Base
end
2. Not performant.




 http://www.flickr.com/photos/danprates/1418154518/
3. Not thread safe.
   No connection pooling.




  http://www.flickr.com/photos/streetmuseo/57990915/
4. Hides SQL from you.




http://www.momentaryfascinations.com/entertainment/the.lost.monty.python.cartoon/still.5.jpg
5. Hard to fight against.




 http://www.mmonotebook.com/wp-content/uploads/2008/04/larp.jpg
6. Encourages stupid databases.
9 ways to bypass
application-level
   constraints
1. Fixtures
2.   Klass.delete(1)
3.   record.save(false)
4.
5. Share DB with a
    second app
6.   User.create(:company_id => 1)
class User < ActiveRecord::Base
7.     has_many :posts
     end
8. ActiveRecord::Base.connection.execute()
9. Errors in your app
        logic
2. Sequel
An object that wraps a row in a database table or view,
encapsulates the database access, and adds domain logic on
that da...
Ruby DSL for SQL

posts = DB[:posts]
posts.filter(:category => /ruby/i, :author => [:jon, :dan])
posts.reverse_order(:crea...
Ruby-like DSL for SQL


posts.filter(:category => :ruby).order(:created_at).select(:title, :author)
ORM
class Post < Sequel::Model
  many_to_many :tags
  many_to_one :author
  validates_presence_of :title
end

post = Post[...
3 interesting things


sequel postgres://localhost:5432/myapp_development
3 interesting things
require 'memcache'
CACHE = MemCache.new 'localhost:11211', :namespace => 'blog'

class Author < Seque...
3 interesting things

DB = Sequel.sqlite('app_test.db',

 :servers=>{:read_only=>{:host=>'slave_server'}})
3. Datamapper
A layer of Mappers (473) that moves data between objects and
a database while keeping them independent of each other and
t...
Multiple Databases

• SQL-based
• In-memory
• Document-based
• Search engines
Explicit property mapping
class Message
  include DataMapper::Resource

  property :name, String
  property :body, Text
  ...
Get only the data you need
Minimize the number of
       queries
Save only the data that
     has changed
Identity Map

repository do
  @parent.children.each do |child|
    puts @parent.object_id = child.parent.object_id
  end
e...
Ruby Query Syntax
Zoo.first(:name.eql => 'Galveston')

Person.all(:age.gt => 30)
Person.all(:age.gte => 30)
Person.all(:na...
Chainable finders
class Zoo
  def self.open
    all(:open => true)
  end

  def self.big
    all(:animal_count.gte => 1000)...
Associations
class Article
  include DataMapper::Resource

  property :id, Serial
  property :title, String
  property :co...
Implicit and explicit
    migrations
Only basic functionality
       in core
Gems for everything else
Is it ready for
  primetime?
Roadmap to 1.0
Rails integration still
        lacking
Not many production
    deployments
Documentation sucks
Some plugins still not
      ported
Thanks!
Dan Weinand
  Jon Dahl
Rails and alternative ORMs
Rails and alternative ORMs
Rails and alternative ORMs
Rails and alternative ORMs
Upcoming SlideShare
Loading in...5
×

Rails and alternative ORMs

6,746

Published 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?

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

No Downloads
Views
Total Views
6,746
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
31
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide


  • So ... Why use an ORM?
  • Because your database and your OO code are unlike things. Different paradigms.



    So in a sense, any time you use a relational DB + OO, you&#x2019;re going to do some sort of object relational mapping.



    May be formal or informal.


  • So data types are not identical
  • Your DB has a formal definition independent of the use of the data.
  • This is a big one.



    In OO, you follow references - an object can &#x201C;point&#x201D; to another object, and so on.



    In SQL, you logically join sets of data together.
  • Any bit of data can be joined to any other bit.



    In OO, ideal is to hide as much as you can and only expose a public interface.
  • declarative vs. active - declare that certain kinds of data are acceptable, vs. actively checking at certain points in time.
  • SQL doesn&#x2019;t directly have a concept of inheritance. Fundamental to OO.


  • Finally, different purposes.



    Define structure for data (and hold that data)



    vs.



    Doing something
  • So basically, ORM are translators between unlike things. Like any translation,
  • this isn&#x2019;t going to be perfectly smooth, and there will always be tradeoffs.



    In this talk, Dan and I are going to talk about these tradeoffs by looking at three approaches to ORM with Ruby.
  • You&#x2019;re probably familiar with this already, so I won&#x2019;t show much code here or talk about how to use AR. Instead, let&#x2019;s talk for a few minutes at a more theoretical level.
  • In this pattern, an object wraps each DB row. This single object handles both domain logic and database access. What's unique about this?
  • Other approaches might not treat each row as an object, or might combine multiple rows into a single object.
  • Others might separate these, filtering the data through a logic layer, instead of exposing both side-by-side.




  • class User < ActiveRecord::Base
    end



    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.



    The good news is that convention dominates. Once you know the conventions, you generally aren't surprised.
  • This is true, by default. N+1, loads all columns, etc.



    It would be really nice if it could do these things.



    But at the same time, it provides facilities for these sorts of optimizations.


  • This is part of the reason that alternative ORMs got started.



    The thing is, it isn't true any more. At least not entirely.


  • This guy, Josh Peek, made Rails 2.2 thread safe.
  • And this guy, who you may recognize, added the current connection pooling.
  • The fact is, as a AR developer, you can pretty much forget how to write a join.



    This isn't really a limitation of AR - some could say that it&#x2019;s a feature. But at the same time, you really do need to know SQL if you&#x2019;re going to use a relational database.



    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...


  • Rails makes polymorphic associations easy and multi-table inheritance hard.



    But polymorphic associations: bad idea. Cuts out a join table, but hurts referential integrity. But because it&#x2019;s easy, you see a lot of it.



    Is this a valid criticism? It usually isn&#x2019;t that hard to fight against AR&#x2019;s conventions, and most of the time, you don&#x2019;t want to.
  • 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.



    You can always run a bare connection.execute() statement, but this won't get dumped into your schema.rb file, which is bad.



    According to DHH et al, you don't need DB constraints, and you want a dumb DB.










  • 4. Access your database directly.


  • Company 1 may not exist.



    Or


  • I.e. you make a mistake
  • I.e. you make a mistake.



    This probably isn&#x2019;t a problem for you, but it might be for some of the other people you work with.
  • Sequel is a thread-safe DB library with a lightweight ORM








  • Follows the ActiveRecord pattern
  • So you don&#x2019;t have to write much real SQL
  • So you don&#x2019;t have to write much real SQL
  • The Sequel ORM is very similar to AR, at least on the surface.



    Does many of the things that Rails does, at least the basics.




  • Also has similar support for sharding










































  • Transcript of "Rails and alternative ORMs"

    1. 1. Rails and Alternative ORMs Dan Weinand Jonathan Dahl
    2. 2. Why?
    3. 3. DB vs. OO declarative vs. imperative
    4. 4. DB vs. OO char/text vs. string
    5. 5. DB vs. OO schema vs. _______
    6. 6. DB vs. OO joins vs. pointers
    7. 7. DB vs. OO public vs. encapsulated
    8. 8. DB vs. OO constraints vs. validation
    9. 9. DB vs. OO _____ vs. inheritance
    10. 10. DB vs. OO DBA vs. programmer
    11. 11. DB vs. OO structure vs. behavior
    12. 12. http://www.engrish.com//wp-content/uploads/2008/08/hand-grenade.jpg
    13. 13. 1. ActiveRecord
    14. 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. 15. One object per row.
    16. 16. Data access and domain logic are done together.
    17. 17. 6 Criticisms of ActiveRecord
    18. 18. 1. Too much magic. http://cgi.ebay.com/MEDIEVAL-MAGE-KING-BLACK-TUNIC-COSTUME-SCA-LARP-_W0QQitemZ250373576829QQcmdZViewItemQQimsxZ20090215?IMSfp=TL090215143008r8810#ebayphotohosting
    19. 19. class User < ActiveRecord::Base end
    20. 20. 2. Not performant. http://www.flickr.com/photos/danprates/1418154518/
    21. 21. 3. Not thread safe. No connection pooling. http://www.flickr.com/photos/streetmuseo/57990915/
    22. 22. 4. Hides SQL from you. http://www.momentaryfascinations.com/entertainment/the.lost.monty.python.cartoon/still.5.jpg
    23. 23. 5. Hard to fight against. http://www.mmonotebook.com/wp-content/uploads/2008/04/larp.jpg
    24. 24. 6. Encourages stupid databases.
    25. 25. 9 ways to bypass application-level constraints
    26. 26. 1. Fixtures
    27. 27. 2. Klass.delete(1)
    28. 28. 3. record.save(false)
    29. 29. 4.
    30. 30. 5. Share DB with a second app
    31. 31. 6. User.create(:company_id => 1)
    32. 32. class User < ActiveRecord::Base 7. has_many :posts end
    33. 33. 8. ActiveRecord::Base.connection.execute()
    34. 34. 9. Errors in your app logic
    35. 35. 2. Sequel
    36. 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. 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. 38. Ruby-like DSL for SQL posts.filter(:category => :ruby).order(:created_at).select(:title, :author)
    39. 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. 40. 3 interesting things sequel postgres://localhost:5432/myapp_development
    41. 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. 42. 3 interesting things DB = Sequel.sqlite('app_test.db', :servers=>{:read_only=>{:host=>'slave_server'}})
    43. 43. 3. Datamapper
    44. 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. 45. Multiple Databases • SQL-based • In-memory • Document-based • Search engines
    46. 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. 47. Get only the data you need
    48. 48. Minimize the number of queries
    49. 49. Save only the data that has changed
    50. 50. Identity Map repository do @parent.children.each do |child| puts @parent.object_id = child.parent.object_id end end
    51. 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. 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. 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. 54. Implicit and explicit migrations
    55. 55. Only basic functionality in core
    56. 56. Gems for everything else
    57. 57. Is it ready for primetime?
    58. 58. Roadmap to 1.0
    59. 59. Rails integration still lacking
    60. 60. Not many production deployments
    61. 61. Documentation sucks
    62. 62. Some plugins still not ported
    63. 63. Thanks! Dan Weinand Jon Dahl
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×