Custom DataMapper
     Adapters
    By Josh Moore (   )
About Me
• Josh Moore

• Optimis Dev

• github.com/joshsmoore

• twitter.com/codingforrent

• www.codingforrent.com

• joshsmoore@gmail.com
DataMapper seams to be losing
 popularity why talk about it?
I enjoy non standard
       things...
It still has features
ActiveRecord/ActiveModel does
                 not...
Try something new...
Examples
class Comment                class Post
  include                      include
      DataMapper::Resource         DataMapper::Resource

 property :id, Serial         property :id, Serial
 property :body, String       property :title, String

  belongs_to :post            has n, :comments
end                          end
Terms
  term                     meaning

Resource                    A model


   field             A property on a model

Repository
             DataMapper term for the storage engine
Preamble
require 'dm-core'
                        Just do it
module DataMapper
                     Just do it
  module Adapters
    class TestAdapter < AbstractAdapter
       ...
    end
                                   Just do it
    const_added(:TestAdapter)
  end
end
Symbol
                                Hash



def initialize(name, options)




end
def initialize(name, options)
          Just do it
 super




end
def initialize(name, options)
 super




end
Connect
                                    to your
def initialize(name, options)      adapter
 super
 @conn = Mongo::Connection.new(
            options[:host], options[:port])
 @adapter = @conn[options[:database]]




end
def initialize(name, options)
 super
 @conn = Mongo::Connection.new(
                  Sub class of: DataMapper::Property
            options[:host], options[:port])
 @adapter = @conn[options[:database]]
 @field_naming_convention = Proc.new do |field|
   field.model.storage_name + '_' + field.name.to_s
 end
                   Return a String




end
def initialize(name, options)
 super
 @conn = Mongo::Connection.new(
             options[:host], options[:port])
 @adapter = @conn[options[:database]]
 @field_naming_convention = Proc.new do |field|
    field.model.storage_name String (class.to_s)
                                    + '_' + field.name.to_s
 end
 @resource_naming_convention = Proc.new do |resource|
    resource.downcase
 end                Return a String
end
def initialize(name, options)
 super
 @conn = Mongo::Connection.new(
             options[:host], options[:port])
 @adapter = @conn[options[:database]]
 @field_naming_convention = Proc.new do |field|
    field.model.storage_name + '_' + field.name.to_s
 end
 @resource_naming_convention = Proc.new do |resource|
    resource.downcase
 end
end
Array of Resources
def create(resources)




end
           Return number of resources created
def create(resources)
 resources.collect do |resource|
   initialize_serial(resource,
      @adapter[resource.class.storage_name].find.count)
   fields = attributes_as_fields(
                 resource.attributes(:property))
   @adapter[resource.class.storage_name].insert(fields)
 end.size

end
def create(resources)
 resources.collect do |resource|
   initialize_serial(resource,
      @adapter[resource.class.storage_name].find.count)
   fields = attributes_as_fields(
                 resource.attributes(:property))
   @adapter[resource.class.storage_name].insert(fields)
 end.size

end
•   Accepts: Hash
                     •   Key: Sub class of: DataMapper::Property
                     •   Value: non marshaled data
                     •   example:

                     {<DataMapper::Property::String(title)>   =>
                     "hasdf"}
def create(resources)
 resources.collect do |resource|
   initialize_serial(resource,
      @adapter[resource.class.storage_name].find.count)
   fields = attributes_as_fields(
                 resource.attributes(:property))
   @adapter[resource.class.storage_name].insert(fields)
 end.size
             • Return: Hash
             • Key: @field_naming_convention result
end          • Value: Marshaled data
             • Only values that are set
             •Example:
             {"post_title" => "hasdf"}
def create(resources)
 resources.collect do |resource|
   initialize_serial(resource,
      @adapter[resource.class.storage_name].find.count)
   fields = attributes_as_fields(
                 resource.attributes(:property))
   @adapter[resource.class.storage_name].insert(fields)
 end.size

end
def create(resources)
 resources.collect do |resource|
   initialize_serial(resource,
      @adapter[resource.class.storage_name].find.count)
   fields = attributes_as_fields(
                 resource.attributes(:property))
   @adapter[resource.class.storage_name].insert(fields)
 end.size

end         Unless an Exception is raised the
           resource will be considered saved
DataMapper::Query

def read(query)




end
              Return a Array of Hashes
                    key: field name
              value: unmarshed value
               {field_name => value}
def read(query)

 conditions = parse_query_conditions(query)
 @adapter[query.model.storage_name].find(
                                 conditions)
end
Query Structure
               DataMapper::Query

                  #conditions


                   Operation

                  #operands


                     Set




 Operation         Condition              Array

                   #subject
       Field                       Association
Query Structure
                          DataMapper::Query

                             #conditions


                              Operation

                             #operands


                                Set




            Operation         Condition              Array

                              #subject
                  Field                       Association



:conditions => ["updated_at > ?", Time.now]
Query Structure
                            DataMapper::Query

                               #conditions


                                Operation

                               #operands


                                  Set




              Operation         Condition              Array

                                #subject
                    Field                       Association



  :conditions => ["updated_at > ?", Time.now]
:conditions => {:updated_at => {"$gte" => Time.now}}
Query Structure
                            DataMapper::Query

                               #conditions


                                Operation

                               #operands


                                  Set




              Operation         Condition
                                                     Hash
                                                      Array

                                #subject
                    Field                       Association



  :conditions => ["updated_at > ?", Time.now]
:conditions => {:updated_at => {"$gte" => Time.now}}
DataMapper::Query

def parse_query_conditions(query)
  mongo_conditions = {}




                                    Return a hash

 mongo_conditions
query.conditions.operands.each do |condition|
         def parse_query_conditions(query)
           mongo_conditions = {}
  case condition.class.to_s
  when 'DataMapper::Query::Conditions::GreaterThanComparison'
    mongo_conditions[condition.subject.field] =
      { "$gt" => condition.value}
  when 'DataMapper::Query::Conditions::LessThanComparison'
    mongo_conditions[condition.subject.field] =
      { "$lt" => condition.value}
  else
    mongo_conditions[condition.subject.field] =
      condition.value
  end      mongo_conditions
end      end
query.conditions.operands.each do |condition|
         def parse_query_conditions(query)
           mongo_conditions = {}
  case condition.class.to_s
  when 'DataMapper::Query::Conditions::GreaterThanComparison'
    mongo_conditions[condition.subject.field] =
      { "$gt" => condition.value}
  when 'DataMapper::Query::Conditions::LessThanComparison'
    mongo_conditions[condition.subject.field] =
      { "$lt" => condition.value}
  else
    mongo_conditions[condition.subject.field] =
      condition.value
  end      mongo_conditions
end      end
query.conditions.operands.each do |condition|
         def parse_query_conditions(query)
           mongo_conditions = {}
  case condition.class.to_s
  when 'DataMapper::Query::Conditions::GreaterThanComparison'
    mongo_conditions[condition.subject.field] =
      { "$gt" => condition.value}
  when 'DataMapper::Query::Conditions::LessThanComparison'
    mongo_conditions[condition.subject.field] =
      { "$lt" => condition.value}
  else
    mongo_conditions[condition.subject.field] =
      condition.value
  end      mongo_conditions
end      end
def parse_query_conditions(query)
  mongo_conditions = {}

 query.conditions.operands.each do |condition|
   case condition.class.to_s
   when 'DataMapper::Query::Conditions::GreaterThanComparison'
     mongo_conditions[condition.subject.field] =
       { "$gt" => condition.value}
   when 'DataMapper::Query::Conditions::LessThanComparison'
     mongo_conditions[condition.subject.field] =
       { "$lt" => condition.value}
   else
     mongo_conditions[condition.subject.field] =
       condition.value
   end
 end

  mongo_conditions
end
Post.all(:comments => {:body => 'hi'})




comments = Comment.all(:body => 'hi')
post_ids = comments.collect { |c| c.post_id }
Post.all(:id => post_ids)
conditions.operands.each do |condition|
  ...
  case condition.class.to_s
  when '...InclusionComparison'
    if condition.subject.instance_of?
DataMapper::Associations::OneToMany::Relationship
      pk = condition.subject.parent_key.first.field
      ck = condition.subject.child_key.first.name
      mongo_conditions[pk] = {"$in" =>
        condition.value.collect {|r| r.send(ck)}}
    else
...
conditions.operands.each do |condition|
  ...
  case condition.class.to_s
  when '...InclusionComparison'
    if condition.subject.instance_of?
DataMapper::Associations::OneToMany::Relationship
      pk = condition.subject.parent_key.first.field
      ck = condition.subject.child_key.first.name
      mongo_conditions[pk] = {"$in" =>
        condition.value.collect {|r| r.send(ck)}}
    else
...
conditions.operands.each do |condition|
  ...   Array of properties
  case condition.class.to_s
        * property - subclass of DataMapper::Property
        * ex. Post#id
  when '...InclusionComparison'
    if condition.subject.instance_of?
DataMapper::Associations::OneToMany::Relationship
      pk = condition.subject.parent_key.first.field
      ck = condition.subject.child_key.first.name
      mongo_conditions[pk] = {"$in" =>
        condition.value.collect {|r| r.send(ck)}}
    elseArray of properties
        * property - subclass of DataMapper::Property
...     * ex Coment#post_id
conditions.operands.each do |condition|
  ...
  case condition.class.to_s
  when '...InclusionComparison'
    if condition.subject.instance_of?
DataMapper::Associations::OneToMany::Relationship
     Array of resources
        pk = condition.subject.parent_key.first.field
     * [#<Comment..>, #<Comment..>,...]

        ck = condition.subject.child_key.first.name
        mongo_conditions[pk] = {"$in" =>
          condition.value.collect {|r| r.send(ck)}}
    else
...
conditions.operands.each do |condition|
  ...
  case condition.class.to_s
  when '...InclusionComparison'
    if condition.subject.instance_of?
DataMapper::Associations::OneToMany::Relationship
      pk = condition.subject.parent_key.first.field
      ck = condition.subject.child_key.first.name
      mongo_conditions[pk] = {"$in" =>
        condition.value.collect {|r| r.send(ck)}}
    else
...
conditions.operands.each do |condition|
  ...
  case condition.class.to_s
  when '...InclusionComparison'
    if condition.subject.instance_of?
DataMapper::Associations::OneToMany::Relationship
      pk = condition.subject.parent_key.first.field
      ck = condition.subject.child_key.first.name
      mongo_conditions[pk] = {"$in" =>
        condition.value.collect {|r| r.send(ck)}}
    else
...
Operation

• DataMapper::Query::Conditions::AndOperation

• DataMapper::Query::Conditions::OrOperation

• DataMapper::Query::Conditions::NotOperation
Condition
• DataMapper::Query::Conditions::EqualToComparison

• DataMapper::Query::Conditions::InclusionComparison

• DataMapper::Query::Conditions::RegexpComparison

• DataMapper::Query::Conditions::LikeComparison

• DataMapper::Query::Conditions::GreaterThanComparison

• DataMapper::Query::Conditions::LessThanComparison

• DataMapper::Query::Conditions::GreaterThanOrEqualToComparison

• DataMapper::Query::Conditions::LessThanOrEqualToComparison
What is not covered


• Nested Operands
If your backed does not
 have a query language
                      A Array of Hashes
                        key: field name
                  value: unmarshed value
                  [{field_name => value}]




def read(query)
  query.filter_records(records)
end
def delete(resources)
  conditions = parse_query_conditions(resources.query)
  record_count = read(resources.query).count
  @adapter[resources.storage_name].remove(conditions)
  record_count
end
DataMapper::Collection

def delete(resources)
  conditions = parse_query_conditions(resources.query)
  record_count = read(resources.query).count
  @adapter[resources.storage_name].remove(conditions)
  record_count
end     Number of resources deleted (int)
def delete(resources)
  conditions = parse_query_conditions(resources.query)
  record_count = read(resources.query).count
  @adapter[resources.storage_name].remove(conditions)
  record_count
end



           Unless an Exception is raised the
          resource will be considered saved
def update(changes, resources)
  conditions = parse_query_conditions(resources.query)
  @adapter[resources.storage_name].update(conditions,
     {"$set" => attributes_as_fields(changes)},
     {:multi => true})
  read(resources.query).count
end
Unmarshaled hash of changes

        {<DataMapper::Property::String(title)>
             => "hasdf"}



                                            DataMapper::Collection

def update(changes, resources)
  conditions = parse_query_conditions(resources.query)
  @adapter[resources.storage_name].update(conditions,
     {"$set" => attributes_as_fields(changes)},
     {:multi => true})
  read(resources.query).count
end
       Number of resources updated (int)
def update(changes, resources)
  conditions = parse_query_conditions(resources.query)
  @adapter[resources.storage_name].update(conditions,
     {"$set" => attributes_as_fields(changes)},
     {:multi => true})
  read(resources.query).count
end
            Unless an Exception is raised the
           resource will be considered saved
Be Kind log


• DataMapper.logger
You can stop now




              end

Dm adapter RubyConf.TW

  • 1.
    Custom DataMapper Adapters By Josh Moore ( )
  • 2.
    About Me • JoshMoore • Optimis Dev • github.com/joshsmoore • twitter.com/codingforrent • www.codingforrent.com • joshsmoore@gmail.com
  • 4.
    DataMapper seams tobe losing popularity why talk about it?
  • 5.
    I enjoy nonstandard things...
  • 6.
    It still hasfeatures ActiveRecord/ActiveModel does not...
  • 7.
  • 8.
    Examples class Comment class Post include include DataMapper::Resource DataMapper::Resource property :id, Serial property :id, Serial property :body, String property :title, String belongs_to :post has n, :comments end end
  • 10.
    Terms term meaning Resource A model field A property on a model Repository DataMapper term for the storage engine
  • 12.
    Preamble require 'dm-core' Just do it module DataMapper Just do it module Adapters class TestAdapter < AbstractAdapter ... end Just do it const_added(:TestAdapter) end end
  • 15.
    Symbol Hash def initialize(name, options) end
  • 16.
    def initialize(name, options) Just do it super end
  • 17.
  • 18.
    Connect to your def initialize(name, options) adapter super @conn = Mongo::Connection.new( options[:host], options[:port]) @adapter = @conn[options[:database]] end
  • 19.
    def initialize(name, options) super @conn = Mongo::Connection.new( Sub class of: DataMapper::Property options[:host], options[:port]) @adapter = @conn[options[:database]] @field_naming_convention = Proc.new do |field| field.model.storage_name + '_' + field.name.to_s end Return a String end
  • 20.
    def initialize(name, options) super @conn = Mongo::Connection.new( options[:host], options[:port]) @adapter = @conn[options[:database]] @field_naming_convention = Proc.new do |field| field.model.storage_name String (class.to_s) + '_' + field.name.to_s end @resource_naming_convention = Proc.new do |resource| resource.downcase end Return a String end
  • 21.
    def initialize(name, options) super @conn = Mongo::Connection.new( options[:host], options[:port]) @adapter = @conn[options[:database]] @field_naming_convention = Proc.new do |field| field.model.storage_name + '_' + field.name.to_s end @resource_naming_convention = Proc.new do |resource| resource.downcase end end
  • 24.
    Array of Resources defcreate(resources) end Return number of resources created
  • 25.
    def create(resources) resources.collectdo |resource| initialize_serial(resource, @adapter[resource.class.storage_name].find.count) fields = attributes_as_fields( resource.attributes(:property)) @adapter[resource.class.storage_name].insert(fields) end.size end
  • 26.
    def create(resources) resources.collectdo |resource| initialize_serial(resource, @adapter[resource.class.storage_name].find.count) fields = attributes_as_fields( resource.attributes(:property)) @adapter[resource.class.storage_name].insert(fields) end.size end
  • 27.
    Accepts: Hash • Key: Sub class of: DataMapper::Property • Value: non marshaled data • example: {<DataMapper::Property::String(title)> => "hasdf"} def create(resources) resources.collect do |resource| initialize_serial(resource, @adapter[resource.class.storage_name].find.count) fields = attributes_as_fields( resource.attributes(:property)) @adapter[resource.class.storage_name].insert(fields) end.size • Return: Hash • Key: @field_naming_convention result end • Value: Marshaled data • Only values that are set •Example: {"post_title" => "hasdf"}
  • 28.
    def create(resources) resources.collectdo |resource| initialize_serial(resource, @adapter[resource.class.storage_name].find.count) fields = attributes_as_fields( resource.attributes(:property)) @adapter[resource.class.storage_name].insert(fields) end.size end
  • 29.
    def create(resources) resources.collectdo |resource| initialize_serial(resource, @adapter[resource.class.storage_name].find.count) fields = attributes_as_fields( resource.attributes(:property)) @adapter[resource.class.storage_name].insert(fields) end.size end Unless an Exception is raised the resource will be considered saved
  • 32.
    DataMapper::Query def read(query) end Return a Array of Hashes key: field name value: unmarshed value {field_name => value}
  • 33.
    def read(query) conditions= parse_query_conditions(query) @adapter[query.model.storage_name].find( conditions) end
  • 34.
    Query Structure DataMapper::Query #conditions Operation #operands Set Operation Condition Array #subject Field Association
  • 35.
    Query Structure DataMapper::Query #conditions Operation #operands Set Operation Condition Array #subject Field Association :conditions => ["updated_at > ?", Time.now]
  • 36.
    Query Structure DataMapper::Query #conditions Operation #operands Set Operation Condition Array #subject Field Association :conditions => ["updated_at > ?", Time.now] :conditions => {:updated_at => {"$gte" => Time.now}}
  • 37.
    Query Structure DataMapper::Query #conditions Operation #operands Set Operation Condition Hash Array #subject Field Association :conditions => ["updated_at > ?", Time.now] :conditions => {:updated_at => {"$gte" => Time.now}}
  • 39.
    DataMapper::Query def parse_query_conditions(query) mongo_conditions = {} Return a hash mongo_conditions
  • 40.
    query.conditions.operands.each do |condition| def parse_query_conditions(query) mongo_conditions = {} case condition.class.to_s when 'DataMapper::Query::Conditions::GreaterThanComparison' mongo_conditions[condition.subject.field] = { "$gt" => condition.value} when 'DataMapper::Query::Conditions::LessThanComparison' mongo_conditions[condition.subject.field] = { "$lt" => condition.value} else mongo_conditions[condition.subject.field] = condition.value end mongo_conditions end end
  • 41.
    query.conditions.operands.each do |condition| def parse_query_conditions(query) mongo_conditions = {} case condition.class.to_s when 'DataMapper::Query::Conditions::GreaterThanComparison' mongo_conditions[condition.subject.field] = { "$gt" => condition.value} when 'DataMapper::Query::Conditions::LessThanComparison' mongo_conditions[condition.subject.field] = { "$lt" => condition.value} else mongo_conditions[condition.subject.field] = condition.value end mongo_conditions end end
  • 42.
    query.conditions.operands.each do |condition| def parse_query_conditions(query) mongo_conditions = {} case condition.class.to_s when 'DataMapper::Query::Conditions::GreaterThanComparison' mongo_conditions[condition.subject.field] = { "$gt" => condition.value} when 'DataMapper::Query::Conditions::LessThanComparison' mongo_conditions[condition.subject.field] = { "$lt" => condition.value} else mongo_conditions[condition.subject.field] = condition.value end mongo_conditions end end
  • 43.
    def parse_query_conditions(query) mongo_conditions = {} query.conditions.operands.each do |condition| case condition.class.to_s when 'DataMapper::Query::Conditions::GreaterThanComparison' mongo_conditions[condition.subject.field] = { "$gt" => condition.value} when 'DataMapper::Query::Conditions::LessThanComparison' mongo_conditions[condition.subject.field] = { "$lt" => condition.value} else mongo_conditions[condition.subject.field] = condition.value end end mongo_conditions end
  • 44.
    Post.all(:comments => {:body=> 'hi'}) comments = Comment.all(:body => 'hi') post_ids = comments.collect { |c| c.post_id } Post.all(:id => post_ids)
  • 45.
    conditions.operands.each do |condition| ... case condition.class.to_s when '...InclusionComparison' if condition.subject.instance_of? DataMapper::Associations::OneToMany::Relationship pk = condition.subject.parent_key.first.field ck = condition.subject.child_key.first.name mongo_conditions[pk] = {"$in" => condition.value.collect {|r| r.send(ck)}} else ...
  • 46.
    conditions.operands.each do |condition| ... case condition.class.to_s when '...InclusionComparison' if condition.subject.instance_of? DataMapper::Associations::OneToMany::Relationship pk = condition.subject.parent_key.first.field ck = condition.subject.child_key.first.name mongo_conditions[pk] = {"$in" => condition.value.collect {|r| r.send(ck)}} else ...
  • 47.
    conditions.operands.each do |condition| ... Array of properties case condition.class.to_s * property - subclass of DataMapper::Property * ex. Post#id when '...InclusionComparison' if condition.subject.instance_of? DataMapper::Associations::OneToMany::Relationship pk = condition.subject.parent_key.first.field ck = condition.subject.child_key.first.name mongo_conditions[pk] = {"$in" => condition.value.collect {|r| r.send(ck)}} elseArray of properties * property - subclass of DataMapper::Property ... * ex Coment#post_id
  • 48.
    conditions.operands.each do |condition| ... case condition.class.to_s when '...InclusionComparison' if condition.subject.instance_of? DataMapper::Associations::OneToMany::Relationship Array of resources pk = condition.subject.parent_key.first.field * [#<Comment..>, #<Comment..>,...] ck = condition.subject.child_key.first.name mongo_conditions[pk] = {"$in" => condition.value.collect {|r| r.send(ck)}} else ...
  • 49.
    conditions.operands.each do |condition| ... case condition.class.to_s when '...InclusionComparison' if condition.subject.instance_of? DataMapper::Associations::OneToMany::Relationship pk = condition.subject.parent_key.first.field ck = condition.subject.child_key.first.name mongo_conditions[pk] = {"$in" => condition.value.collect {|r| r.send(ck)}} else ...
  • 50.
    conditions.operands.each do |condition| ... case condition.class.to_s when '...InclusionComparison' if condition.subject.instance_of? DataMapper::Associations::OneToMany::Relationship pk = condition.subject.parent_key.first.field ck = condition.subject.child_key.first.name mongo_conditions[pk] = {"$in" => condition.value.collect {|r| r.send(ck)}} else ...
  • 51.
  • 52.
    Condition • DataMapper::Query::Conditions::EqualToComparison • DataMapper::Query::Conditions::InclusionComparison •DataMapper::Query::Conditions::RegexpComparison • DataMapper::Query::Conditions::LikeComparison • DataMapper::Query::Conditions::GreaterThanComparison • DataMapper::Query::Conditions::LessThanComparison • DataMapper::Query::Conditions::GreaterThanOrEqualToComparison • DataMapper::Query::Conditions::LessThanOrEqualToComparison
  • 53.
    What is notcovered • Nested Operands
  • 54.
    If your backeddoes not have a query language A Array of Hashes key: field name value: unmarshed value [{field_name => value}] def read(query) query.filter_records(records) end
  • 56.
    def delete(resources) conditions = parse_query_conditions(resources.query) record_count = read(resources.query).count @adapter[resources.storage_name].remove(conditions) record_count end
  • 57.
    DataMapper::Collection def delete(resources) conditions = parse_query_conditions(resources.query) record_count = read(resources.query).count @adapter[resources.storage_name].remove(conditions) record_count end Number of resources deleted (int)
  • 58.
    def delete(resources) conditions = parse_query_conditions(resources.query) record_count = read(resources.query).count @adapter[resources.storage_name].remove(conditions) record_count end Unless an Exception is raised the resource will be considered saved
  • 60.
    def update(changes, resources) conditions = parse_query_conditions(resources.query) @adapter[resources.storage_name].update(conditions, {"$set" => attributes_as_fields(changes)}, {:multi => true}) read(resources.query).count end
  • 61.
    Unmarshaled hash ofchanges {<DataMapper::Property::String(title)> => "hasdf"} DataMapper::Collection def update(changes, resources) conditions = parse_query_conditions(resources.query) @adapter[resources.storage_name].update(conditions, {"$set" => attributes_as_fields(changes)}, {:multi => true}) read(resources.query).count end Number of resources updated (int)
  • 62.
    def update(changes, resources) conditions = parse_query_conditions(resources.query) @adapter[resources.storage_name].update(conditions, {"$set" => attributes_as_fields(changes)}, {:multi => true}) read(resources.query).count end Unless an Exception is raised the resource will be considered saved
  • 63.
    Be Kind log •DataMapper.logger
  • 64.
    You can stopnow end

Editor's Notes

  • #2 \n
  • #3 * Work mostly with backend data transformations from Transactional Database to Reporting datastore\n* When you have a child the blogging slows down\n* Talk quickly when I am nervous, let me know if to fast\n
  • #4 \n
  • #5 \n
  • #6 * About the little ruby Code in the middle\n* Will not focus on either DB OR DM\n
  • #7 * last commit was almost a month ago\n* It is true\n* ActiveRecord lots of improvements\n
  • #8 \n
  • #9 \n
  • #10 * Associations across multiple repositories\n
  • #11 * &amp;#x738B;&amp;#x5EFA;&amp;#x8208; talked about picking different things from different languages... Why not learn different ORMs to?\n
  • #12 \n
  • #13 * xdite will think it is stupid\n
  • #14 \n
  • #15 * With the addition of the initialization mostly just CRUD operations\n* CRUD\n
  • #16 \n
  • #17 \n
  • #18 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #19 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #20 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #21 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #22 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #23 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #24 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #25 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #26 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #27 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #28 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #29 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #30 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #31 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #32 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #33 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #34 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #35 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #36 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #37 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #38 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #39 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #40 * Raw Access to connection through adapter\n* Persisted through entire instance, so if time out need to reconnect\n
  • #41 \n
  • #42 \n
  • #43 \n
  • #44 \n
  • #45 \n
  • #46 \n
  • #47 \n
  • #48 \n
  • #49 \n
  • #50 \n
  • #51 \n
  • #52 \n
  • #53 \n
  • #54 \n
  • #55 \n
  • #56 \n
  • #57 \n
  • #58 \n
  • #59 \n
  • #60 \n
  • #61 \n
  • #62 \n
  • #63 \n
  • #64 \n
  • #65 \n
  • #66 \n
  • #67 \n
  • #68 \n
  • #69 \n
  • #70 \n
  • #71 \n
  • #72 \n
  • #73 \n
  • #74 \n
  • #75 \n
  • #76 \n
  • #77 \n
  • #78 \n
  • #79 \n
  • #80 * Association - subclass of DataMapper::Associations::*::Relationship\n* Field - subclass of DataMapper::Property\n
  • #81 * Association - subclass of DataMapper::Associations::*::Relationship\n* Field - subclass of DataMapper::Property\n
  • #82 * Association - subclass of DataMapper::Associations::*::Relationship\n* Field - subclass of DataMapper::Property\n
  • #83 * Association - subclass of DataMapper::Associations::*::Relationship\n* Field - subclass of DataMapper::Property\n
  • #84 * Only top level Operation\n* own your own for recursive solution\n
  • #85 * Only top level Operation\n* own your own for recursive solution\n
  • #86 * Only top level Operation\n* own your own for recursive solution\n
  • #87 * Only top level Operation\n* own your own for recursive solution\n
  • #88 * Only top level Operation\n* own your own for recursive solution\n
  • #89 * Only top level Operation\n* own your own for recursive solution\n
  • #90 * Only top level Operation\n* own your own for recursive solution\n
  • #91 * Only top level Operation\n* own your own for recursive solution\n
  • #92 * Only top level Operation\n* own your own for recursive solution\n
  • #93 * Only top level Operation\n* own your own for recursive solution\n
  • #94 * Only top level Operation\n* own your own for recursive solution\n
  • #95 * Only top level Operation\n* own your own for recursive solution\n
  • #96 * Only top level Operation\n* own your own for recursive solution\n
  • #97 * Only top level Operation\n* own your own for recursive solution\n
  • #98 * Only top level Operation\n* own your own for recursive solution\n
  • #99 * Only top level Operation\n* own your own for recursive solution\n
  • #100 * Only top level Operation\n* own your own for recursive solution\n
  • #101 * Only top level Operation\n* own your own for recursive solution\n
  • #102 * Only top level Operation\n* own your own for recursive solution\n
  • #103 \n
  • #104 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #105 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #106 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #107 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #108 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #109 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #110 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #111 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #112 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #113 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #114 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #115 * .field - the repository name\n* .name - the resource name\n* value IS UNMARSHALED \n
  • #116 \n
  • #117 \n
  • #118 \n
  • #119 \n
  • #120 \n
  • #121 \n
  • #122 \n
  • #123 \n
  • #124 \n
  • #125 \n
  • #126 \n
  • #127 \n
  • #128 \n
  • #129 \n
  • #130 \n
  • #131 \n
  • #132 \n
  • #133 \n
  • #134 \n
  • #135 \n
  • #136 \n
  • #137 \n
  • #138 \n
  • #139 \n
  • #140 \n
  • #141 \n
  • #142 \n
  • #143 \n
  • #144 \n
  • #145 \n
  • #146 \n
  • #147 \n
  • #148 * info - used for logging what you are sending to the repository\n
  • #149 \n
  • #150 * The first part of the presentation is the 80 percent that makes the most difference\n* The last (more repository specific) part is the 20 percent\n
  • #151 * Mongo specific example \n* But demonstrates the process of modifying a models\n
  • #152 \n
  • #153 \n
  • #154 \n
  • #155 \n
  • #156 \n
  • #157 \n
  • #158 \n
  • #159 \n
  • #160 \n
  • #161 \n
  • #162 \n
  • #163 \n
  • #164 \n
  • #165 \n
  • #166 \n
  • #167 * Be kind log\n* at info log the query parameters that are being passed to repository\n* Mongo supports Array and Hash natively\n
  • #168 \n
  • #169 \n
  • #170 \n
  • #171 \n
  • #172 \n