DataMapper的auto_upgrade如何工作?

时间:2014-09-20 05:02:45

标签: ruby sinatra database-migration ruby-datamapper

您能否告诉我Data Mapper的自动升级功能如何运作?

例如:

include 'data_mapper'
DataMapper.setup :default, "sqlite://#{Dir.pwd}/base.db"

class User
   include DataMapper::Resource
   property :id, Serial
   property :name, String
end

DataMapper.auto_upgrade!

此处,Data Mapper的自动升级如何理解他们必须创建数据库

1 个答案:

答案 0 :(得分:1)

首先,User类数据库,它是模型,它链接到中的< EM>数据库

当您include DataMapper::Resource时,它会自动调用extend DataMapper::Model

# https://github.com/datamapper/dm-core/blob/master/lib/dm-core/resource.rb#L55-L58

module DataMapper
  module Resource
    # ...

    def self.included(model)
      model.extend Model
      super
    end

    # ...
  end
end

此扩展调用被DataMapper::Model中的另一个钩子拦截,该钩子跟踪模块的后代:

# https://github.com/datamapper/dm-core/blob/master/lib/dm-core/model.rb#L209-L223

module DataMapper
  module Model
    # ...

    def self.descendants
      @descendants ||= DescendantSet.new
    end

    # ...

    def self.extended(descendant)
      descendants << descendant
      # ...
      super
    end

    # ...
  end
end

稍后,DataMapper可以通过DataMapper::Model.descendants找到所有模型:

# https://github.com/datamapper/dm-migrations/blob/8bfcec08286a12ceee1bc3e5a01da3b5b7d4a74d/lib/dm-migrations/auto_migration.rb#L43-L50

module DataMapper
  module Migrations
    module SingletonMethods
      # ...

      def auto_upgrade!(repository_name = nil)
        repository_execute(:auto_upgrade!, repository_name)
      end

      # ...

      def repository_execute(method, repository_name)
        models = DataMapper::Model.descendants
        models = models.select { |m| m.default_repository_name == repository_name } if repository_name
        models.each do |model|
          model.send(method, model.default_repository_name)
        end
      end

      # ...
    end
  end
end

这是一个最小的例子:

module Model
  def self.descendants
    @descendants ||= []
  end

  def self.extended(base)
    descendants << base
    super
  end
end

module Resource
  def self.included(base)
    base.extend(Model)
  end
end

class Car
  include Resource
end

class Bike
  include Resource
end

class Train
  include Resource
end

Model.descendants
#=> [Car, Bike, Train]