forked from mongodb/mongoid
-
Notifications
You must be signed in to change notification settings - Fork 22
/
mongoid.rb
180 lines (164 loc) · 5.4 KB
/
mongoid.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# encoding: utf-8
module Rails
module Mongoid
extend self
# 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 [ Array<String> ] globs The file matching globs.
#
# @return [ Array<Class> ] The indexed models.
#
# @since 2.1.0
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.compact
end
# 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 [ Array<String> ] globs The file matching globs.
#
# @return [ Array<Class> ] The un-indexed models.
#
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(', ')}.")
model
end.compact
end
# 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. Return all models under app/models/
# Rails::Mongoid.models
# Rails::Mongoid.models("app/models/**/*.rb")
#
# @param [ String ] glob The file matching glob.
#
# @return [ Array<Class> ] The models.
#
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
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
# that indexing and inheritance work in both development and production
# with the same results.
#
# @example Load all the application models.
# Rails::Mongoid.load_models(app)
#
# @param [ Application ] app The rails application.
def load_models(app)
app.config.paths["app/models"].each do |path|
preload = ::Mongoid.preload_models
if preload.resizable?
files = preload.map { |model| "#{path}/#{model}.rb" }
else
files = Dir.glob("#{path}/**/*.rb")
end
files.sort.each do |file|
load_model(file.gsub("#{path}/" , "").gsub(".rb", ""))
end
end
end
# Conditionally calls `Rails::Mongoid.load_models(app)` if the
# `::Mongoid.preload_models` is `true`.
#
# @param [ Application ] app The rails application.
def preload_models(app)
load_models(app) if ::Mongoid.preload_models
end
private
# I don't want to mock out kernel for unit testing purposes, so added this
# method as a convenience.
#
# @example Load the model.
# Mongoid.load_model("/mongoid/behaviour")
#
# @param [ String ] file The base filename.
#
# @since 2.0.0.rc.3
def load_model(file)
begin
require_dependency(file)
rescue Exception => e
Logger.new($stdout).warn(e.message)
end
end
# Given the provided file name, determine the model and return the class.
#
# @example Determine the model from the file.
# Rails::Mongoid.determine_model("app/models/person.rb")
#
# @param [ String ] file The filename.
#
# @return [ Class ] The model.
#
# @since 2.1.0
def determine_model(file, logger)
return nil unless file =~ /app\/models\/(.*).rb$/
return nil unless logger
model_path = $1.split('/')
begin
parts = model_path.map { |path| path.camelize }
name = parts.join("::")
klass = name.constantize
rescue NameError, LoadError
logger.info("MONGOID: Attempted to constantize #{name}, trying without namespacing.")
klass = parts.last.constantize
end
klass if klass.ancestors.include?(::Mongoid::Document)
end
# Private logger object
#
def logger
@logger ||= Logger.new($stdout)
end
end
end