Skip to content

Instantly share code, notes, and snippets.

@emmanuel
Forked from FND/.gitignore
Created October 18, 2011 23:50
Show Gist options
  • Select an option

  • Save emmanuel/1297105 to your computer and use it in GitHub Desktop.

Select an option

Save emmanuel/1297105 to your computer and use it in GitHub Desktop.

Revisions

  1. emmanuel revised this gist Oct 18, 2011. 2 changed files with 3 additions and 28 deletions.
    2 changes: 1 addition & 1 deletion dm_el.rb
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@
    require 'dm-core'
    require 'dm-constraints'
    require 'dm-migrations'
    require 'eager_loading'
    require File.expand_path('../eager_loading', __FILE__)

    DataMapper::Logger.new($stdout, :debug)
    DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/db.sqlite")
    29 changes: 2 additions & 27 deletions eager_loading.rb
    Original file line number Diff line number Diff line change
    @@ -1,34 +1,9 @@
    # manual eager loading for DataMapper
    # adapted from Chris Corbyn: https://gist.github.com/1244491#gistcomment-56797
    module EagerLoading

    def eager_load(query_path)
    scope = self

    query_path.relationships.each do |relation|
    source_key = relation.source_key.first # TODO: rename
    target_key = relation.target_key.first # TODO: rename

    # for each level in the query path, collect all the resources referencing
    # keys at the current scope
    next_scope = relation.target_model.all(target_key.name => scope.
    collect(&:"#{source_key.name}"))

    # map target keys to the resources that exist for them
    links = next_scope.inject({}) do |map, resource|
    map.merge(target_key.get(resource) => [resource]) { |k, v1, v2| v1 + v2 }
    end

    # now pre-load those from the map
    scope.each do |parent|
    if links.key?(source_key.get(parent))
    parent.instance_variable_set(:"@#{relation.name}",
    links[source_key.get(parent)])
    end
    end

    # and step into the next nesting level
    scope = next_scope
    query_path.relationships.inject(self) do |collection, relationship|
    relationship.eager_load(collection)
    end

    self
  2. FND revised this gist Oct 17, 2011. 2 changed files with 51 additions and 1 deletion.
    13 changes: 12 additions & 1 deletion dm_el.rb
    Original file line number Diff line number Diff line change
    @@ -7,6 +7,7 @@
    require 'dm-core'
    require 'dm-constraints'
    require 'dm-migrations'
    require 'eager_loading'

    DataMapper::Logger.new($stdout, :debug)
    DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/db.sqlite")
    @@ -89,7 +90,7 @@ class Manufacturer
    end
    end

    puts "", '[INFO] test case C ===== /!\ n+1 hazard ===='
    puts "", "[INFO] test case C ===== /!\ n+1 hazard ===="
    people = Person.all
    people.each do |person|
    person.vehicles.each do |vehicle|
    @@ -98,3 +99,13 @@ class Manufacturer
    end
    end
    end

    puts "", "[INFO] test case D"
    people = Person.all
    people.eager_load(Person.vehicles.components).each do |person|
    person.vehicles.each do |vehicle|
    vehicle.components.each do |component|
    puts sprintf("%-10s %-10s %-10s", person.name, vehicle.name, component.name)
    end
    end
    end
    39 changes: 39 additions & 0 deletions eager_loading.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,39 @@
    # manual eager loading for DataMapper
    # adapted from Chris Corbyn: https://gist.github.com/1244491#gistcomment-56797
    module EagerLoading

    def eager_load(query_path)
    scope = self

    query_path.relationships.each do |relation|
    source_key = relation.source_key.first # TODO: rename
    target_key = relation.target_key.first # TODO: rename

    # for each level in the query path, collect all the resources referencing
    # keys at the current scope
    next_scope = relation.target_model.all(target_key.name => scope.
    collect(&:"#{source_key.name}"))

    # map target keys to the resources that exist for them
    links = next_scope.inject({}) do |map, resource|
    map.merge(target_key.get(resource) => [resource]) { |k, v1, v2| v1 + v2 }
    end

    # now pre-load those from the map
    scope.each do |parent|
    if links.key?(source_key.get(parent))
    parent.instance_variable_set(:"@#{relation.name}",
    links[source_key.get(parent)])
    end
    end

    # and step into the next nesting level
    scope = next_scope
    end

    self
    end

    end

    DataMapper::Collection.send(:include, EagerLoading)
  3. FND revised this gist Sep 30, 2011. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dm_el.rb
    Original file line number Diff line number Diff line change
    @@ -89,7 +89,7 @@ class Manufacturer
    end
    end

    puts "", "[INFO] test case C"
    puts "", '[INFO] test case C ===== /!\ n+1 hazard ===='
    people = Person.all
    people.each do |person|
    person.vehicles.each do |vehicle|
  4. FND revised this gist Sep 27, 2011. 2 changed files with 3 additions and 3 deletions.
    4 changes: 2 additions & 2 deletions dm_el.rb
    Original file line number Diff line number Diff line change
    @@ -85,7 +85,7 @@ class Manufacturer
    people = Person.all
    people.each do |person|
    person.vehicles.each do |vehicle|
    puts sprintf("%-20s %-20s", person.name, vehicle.name)
    puts sprintf("%-10s %-10s", person.name, vehicle.name)
    end
    end

    @@ -94,7 +94,7 @@ class Manufacturer
    people.each do |person|
    person.vehicles.each do |vehicle|
    vehicle.components.each do |component|
    puts sprintf("%-20s %-20s %-20s", person.name, vehicle.name, component.name)
    puts sprintf("%-10s %-10s %-10s", person.name, vehicle.name, component.name)
    end
    end
    end
    2 changes: 1 addition & 1 deletion run.sh
    Original file line number Diff line number Diff line change
    @@ -3,4 +3,4 @@
    rm db.sqlite

    # reformat SQL queries for readability
    ./dm_el.rb | perl -pe 's|SELECT .*? (FROM ".*?" )(.*)|\1SELECT ... \2|'
    bundle exec ./dm_el.rb | perl -pe 's#SELECT .*? (FROM ".*?" )(.*)#\1SELECT ... \2#'
  5. FND revised this gist Sep 27, 2011. 1 changed file with 13 additions and 0 deletions.
    13 changes: 13 additions & 0 deletions dm_el.rb
    Original file line number Diff line number Diff line change
    @@ -77,6 +77,19 @@ class Manufacturer

    # retrieve data

    puts "", "[INFO] test case A"
    person = Person.get!(1)
    puts person.vehicles.components.manufacturer.map(&:name).join(", ")

    puts "", "[INFO] test case B"
    people = Person.all
    people.each do |person|
    person.vehicles.each do |vehicle|
    puts sprintf("%-20s %-20s", person.name, vehicle.name)
    end
    end

    puts "", "[INFO] test case C"
    people = Person.all
    people.each do |person|
    person.vehicles.each do |vehicle|
  6. FND revised this gist Sep 27, 2011. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions run.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,6 @@
    #!/usr/bin/env sh

    rm db.sqlite

    # reformat SQL queries for readability
    ./dm_el.rb | perl -pe 's|SELECT .*? (FROM ".*?" )(.*)|\1SELECT ... \2|'
  7. FND revised this gist Sep 27, 2011. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions dm_el.rb
    Original file line number Diff line number Diff line change
    @@ -74,3 +74,14 @@ class Manufacturer
    :manufacturer => Manufacturer.create(:name => "VW"))
    ])
    ])

    # retrieve data

    people = Person.all
    people.each do |person|
    person.vehicles.each do |vehicle|
    vehicle.components.each do |component|
    puts sprintf("%-20s %-20s %-20s", person.name, vehicle.name, component.name)
    end
    end
    end
  8. FND revised this gist Sep 27, 2011. 1 changed file with 26 additions and 2 deletions.
    28 changes: 26 additions & 2 deletions dm_el.rb
    Original file line number Diff line number Diff line change
    @@ -17,11 +17,11 @@ class Person
    property :id, Serial
    property :name, String, :required => true

    has n, :cars
    has n, :vehicles

    end

    class Car
    class Vehicle
    include DataMapper::Resource

    property :id, Serial
    @@ -50,3 +50,27 @@ class Manufacturer
    end

    DataMapper.auto_migrate!

    # generate test data

    Person.create(:name => "FND", :vehicles => [
    Vehicle.create(:name => "Taurus", :components => [
    Component.create(:name => "engine",
    :manufacturer => Manufacturer.create(:name => "Ford")),
    Component.create(:name => "radio",
    :manufacturer => Manufacturer.create(:name => "Bose"))
    ]),
    Vehicle.create(:name => "fixie", :components => [
    Component.create(:name => "frame",
    :manufacturer => Manufacturer.create(:name => "Campagnolo")),
    Component.create(:name => "breaks",
    :manufacturer => Manufacturer.create(:name => "Shimano"))
    ])
    ])

    Person.create(:name => "tillsc", :vehicles => [
    Vehicle.create(:name => "Golf", :components => [
    Component.create(:name => "engine",
    :manufacturer => Manufacturer.create(:name => "VW"))
    ])
    ])
  9. FND revised this gist Sep 27, 2011. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dm_el.rb
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@
    require 'dm-migrations'

    DataMapper::Logger.new($stdout, :debug)
    DataMapper.setup(:default, "sqlite3://db.sqlite")
    DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/db.sqlite")

    class Person
    include DataMapper::Resource
  10. FND revised this gist Sep 27, 2011. 3 changed files with 9 additions and 0 deletions.
    1 change: 1 addition & 0 deletions .gitignore
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    Gemfile.lock
    8 changes: 8 additions & 0 deletions Gemfile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    source :rubygems

    DM_VERSION = '~> 1.2.0.rc2'

    gem 'dm-core', DM_VERSION
    gem 'dm-constraints', DM_VERSION
    gem 'dm-migrations', DM_VERSION
    gem 'dm-sqlite-adapter', DM_VERSION
    Empty file modified dm_el.rb
    100644 → 100755
    Empty file.
  11. @FND FND created this gist Sep 27, 2011.
    52 changes: 52 additions & 0 deletions dm_el.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    #!/usr/bin/env ruby
    # encoding: UTF-8

    # test case for eager loading of nested associations with DataMapper

    require 'rubygems'
    require 'dm-core'
    require 'dm-constraints'
    require 'dm-migrations'

    DataMapper::Logger.new($stdout, :debug)
    DataMapper.setup(:default, "sqlite3://db.sqlite")

    class Person
    include DataMapper::Resource

    property :id, Serial
    property :name, String, :required => true

    has n, :cars

    end

    class Car
    include DataMapper::Resource

    property :id, Serial
    property :name, String, :required => true

    has n, :components

    end

    class Component
    include DataMapper::Resource

    property :id, Serial
    property :name, String, :required => true

    belongs_to :manufacturer

    end

    class Manufacturer
    include DataMapper::Resource

    property :id, Serial
    property :name, String, :required => true

    end

    DataMapper.auto_migrate!