Permalink
Browse files

more accurate model tracking makes tasks non-broken

  • Loading branch information...
1 parent 31c8b39 commit b819dfde339b71b5772da4028a7a9d033edab91b @ahoward ahoward committed with durran Nov 8, 2012
View
@@ -151,6 +151,15 @@ def session(name)
Sessions.with_name(name)
end
+ # Return the list of all known Mongoid models
+ #
+ # @return [ Array<Class> ] All Mongoid models
+ #
+ # @since 3.1.0
+ def models
+ Document.models
+ end
+
# Take all the public instance methods from the Config singleton and allow
# them to be accessed through the Mongoid module directly.
#
View
@@ -359,6 +359,28 @@ def logger
Mongoid.logger
end
end
+
+ # Track all document classes
+ #
+ # @return [ Array<Class> ] All document classes
+ #
+ # @since 3.1.0
+ def Document.included(other)
+ super
+ ensure
+ Mongoid.models.delete_if{|model| model.name == other.name}
+ Mongoid.models.push(other)
+ end
+
+ # Returns the list of all classes known to have included
+ # Mongoid::Document
+ #
+ # @return [ Array<Class> ] All document classes
+ #
+ # @since 3.1.0
+ def Document.models
+ @models ||= []
+ end
end
end
@@ -66,31 +66,14 @@ namespace :db do
end
namespace :mongoid do
-
desc "Create the indexes defined on your mongoid models"
task :create_indexes => :environment do
- engines_models_paths = Rails.application.railties.engines.map do |engine|
- engine.paths["app/models"].expanded
- end
- root_models_paths = Rails.application.paths["app/models"]
- models_paths = engines_models_paths.push(root_models_paths).flatten
-
- models_paths.each do |path|
- ::Rails::Mongoid.create_indexes("#{path}/**/*.rb")
- end
+ ::Rails::Mongoid.create_indexes
end
desc "Remove the indexes defined on your mongoid models without questions!"
task :remove_indexes => :environment do
- engines_models_paths = Rails.application.railties.engines.map do |engine|
- engine.paths["app/models"].expanded
- end
- root_models_paths = Rails.application.paths["app/models"]
- models_paths = engines_models_paths.push(root_models_paths).flatten
-
- models_paths.each do |path|
- ::Rails::Mongoid.remove_indexes("#{path}/**/*.rb")
- end
+ ::Rails::Mongoid.remove_indexes
end
desc "Drops the database for the current Rails.env"
View
@@ -3,76 +3,96 @@ module Rails
module Mongoid
extend self
- # Create indexes for each model given the provided pattern and the class is
+ # Create indexes for each model given the provided globs and the class is
# not embedded.
#
# @example Create all the indexes.
# Rails::Mongoid.create_indexes("app/models/**/*.rb")
#
- # @param [ String ] pattern The file matching pattern.
+ # @param [ Array<String> ] globs The file matching globs.
#
- # @return [ Array<String> ] The file names.
+ # @return [ Array<Class> ] The indexed models.
#
# @since 2.1.0
- def create_indexes(pattern)
- logger = Logger.new($stdout)
- models(pattern).each do |model|
+ def create_indexes(*globs)
+ models(*globs).each do |model|
next if model.index_options.empty?
unless model.embedded?
model.create_indexes
logger.info("MONGOID: Created indexes on #{model}:")
model.index_options.each_pair do |index, options|
logger.info("MONGOID: Index: #{index}, Options: #{options}")
end
+ model
else
logger.info("MONGOID: Index ignored on: #{model}, please define in the root model.")
+ nil
end
- end
+ end.compact
end
- # Remove indexes for each model given the provided pattern and the class is
+ # Remove indexes for each model given the provided globs and the class is
# not embedded.
#
# @example Remove all the indexes.
# Rails::Mongoid.create_indexes("app/models/**/*.rb")
#
- # @param [ String ] pattern The file matching pattern.
+ # @param [ Array<String> ] globs The file matching globs.
#
- # @return [ Array<String> ] The file names.
+ # @return [ Array<Class> ] The un-indexed models.
#
- def remove_indexes(pattern)
- logger = Logger.new($stdout)
- models(pattern).each do |model|
+ def remove_indexes(*globs)
+ models(*globs).each do |model|
next if model.embedded?
indexes = model.collection.indexes.map{ |doc| doc["name"] }
indexes.delete_one("_id_")
model.remove_indexes
logger.info("MONGOID: Removing indexes on: #{model} for: #{indexes.join(', ')}.")
- end
+ model
+ end.compact
end
- # Return all models matching the pattern.
+ # Return all models matching the globs or, if no globs are specified, all
+ # possible models known from engines, the app, any gems, etc.
#
- # @example Return all models.
+ # @example Return *all* models. Return all models under app/models/
+ # Rails::Mongoid.models
# Rails::Mongoid.models("app/models/**/*.rb")
#
- # @param [ String ] pattern The file matching pattern.
+ # @param [ String ] glob The file matching glob.
#
# @return [ Array<Class> ] The models.
#
- def models(pattern)
- Dir.glob(pattern).map do |file|
- logger = Logger.new($stdout)
- begin
- determine_model(file, logger)
- rescue => e
- logger.error(%Q{MONGOID: Failed to determine model from #{file}:
- #{e.class}:#{e.message}
- #{e.backtrace.join("\n")}
- })
- nil
+ def models(*globs)
+ all_possible_models = globs.empty?
+
+ if globs.empty?
+ engines_models_paths = Rails.application.railties.engines.map{|engine| engine.paths["app/models"].expanded}
+ root_models_paths = Rails.application.paths["app/models"]
+ models_paths = engines_models_paths.push(root_models_paths).flatten
+ globs.replace(models_paths.map{|path| "#{path}/**/*.rb"})
+ end
+
+ models = []
+
+ globs.flatten.compact.each do |glob|
+ Dir.glob(glob).map do |file|
+ begin
+ model = determine_model(file, logger)
+ models.push(model)
+ rescue => e
+ logger.error(%Q{MONGOID: Failed to determine model from #{file}:
+ #{e.class}:#{e.message}
+ #{e.backtrace.join("\n")}
+ })
+ nil
+ end
end
- end.flatten.compact
+ end
+
+ models = (::Mongoid.models | models) if all_possible_models
+
+ models.compact.sort_by{|model| model.name || ''}
end
# Use the application configuration to get every model and require it, so
@@ -150,5 +170,11 @@ def determine_model(file, logger)
end
klass if klass.ancestors.include?(::Mongoid::Document)
end
+
+ # Private logger object
+ #
+ def logger
+ @logger ||= Logger.new($stdout)
+ end
end
end
@@ -14,6 +14,62 @@
person.should_not respond_to(:_destroy)
end
+ describe ".included" do
+ let(:models) do
+ Mongoid::Document.models
+ end
+
+ let(:new_klass_name) do
+ 'NewKlassName'
+ end
+
+ let(:new_klass) do
+ Class.new do
+ class << self; attr_accessor :name; end
+ end.tap{|new_klass| new_klass.name = new_klass_name}
+ end
+
+ let(:new_model) do
+ new_klass.tap do
+ new_klass.send(:include, ::Mongoid::Document)
+ end
+ end
+
+ let(:twice_a_new_model) do
+ new_klass.tap do
+ 2.times{ new_klass.send(:include, ::Mongoid::Document) }
+ end
+ end
+
+ it "should respond to :models" do
+ Mongoid::Document.should respond_to(:models)
+ end
+
+ context "when Document has been included in a model" do
+ it ".models should include that model" do
+ models.should include(klass)
+ end
+ end
+
+ context "before Document has been included" do
+ it ".models should *not* include that model" do
+ models.should_not include(new_klass)
+ end
+ end
+
+ context "after Document has been included" do
+ it ".models should include that model" do
+ models.should include(new_model)
+ end
+ end
+
+ context "after Document has been included multiple times" do
+ it ".models should include that model just once" do
+ models.count(twice_a_new_model).should be_eql(1)
+ end
+ end
+ end
+
describe "#==" do
context "when comparable is not a document" do
View
@@ -64,4 +64,10 @@
Mongoid.session(:default).should eq(Mongoid::Sessions.default)
end
end
+
+ describe ".models" do
+ it "returns the list of known models" do
+ Mongoid.models.should eq(Mongoid::Document.models)
+ end
+ end
end
@@ -30,14 +30,12 @@
before do
Dir.should_receive(:glob).once.with(pattern).and_return(model_paths)
- Logger.should_receive(:new).twice.and_return(logger)
end
context "with ordinary Rails models" do
it "creates the indexes for the models" do
klass.should_receive(:create_indexes).once
- logger.should_receive(:info).twice
indexes
end
end
@@ -83,7 +81,6 @@
it "does nothing, but logging" do
klass.should_receive(:create_indexes).never
- logger.should_receive(:info).once
indexes
end
end
@@ -109,8 +106,6 @@
before do
Dir.should_receive(:glob).with(pattern).exactly(2).times.and_return(model_paths)
- Logger.should_receive(:new).exactly(4).times.and_return(logger)
- logger.should_receive(:info).exactly(3).times
end
let(:indexes) do

0 comments on commit b819dfd

Please sign in to comment.