mongo_mapper_ext 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +68 -0
- data/lib/mongo_mapper_ext/db_config.rb +67 -0
- data/lib/mongo_mapper_ext/hacks/fixes.rb +20 -0
- data/lib/mongo_mapper_ext/hacks/time_measuring.rb +44 -0
- data/lib/mongo_mapper_ext/micelaneous.rb +53 -0
- data/lib/mongo_mapper_ext/migrate.rake +33 -0
- data/lib/mongo_mapper_ext/migration.rb +108 -0
- data/lib/mongo_mapper_ext/mongo_mapper.rb +25 -0
- data/lib/mongo_mapper_ext/plugins/attributes_cache.rb +22 -0
- data/lib/mongo_mapper_ext/plugins/db_config.rb +47 -0
- data/lib/mongo_mapper_ext/plugins/default_scope.rb +80 -0
- data/lib/mongo_mapper_ext/plugins/micelaneous.rb +97 -0
- data/lib/mongo_mapper_ext/spec/helper.rb +61 -0
- data/lib/mongo_mapper_ext/view_helpers.rb +10 -0
- data/lib/mongo_mapper_ext.rb +32 -0
- data/readme.md +3 -0
- data/spec/helper.rb +8 -0
- data/spec/micelaneous_plugin_spec.rb +56 -0
- data/spec/micelaneous_spec.rb +53 -0
- data/spec/migration_spec.rb +79 -0
- data/spec/mm_spec.rb +35 -0
- data/spec/scope_spec.rb +124 -0
- data/spec/spec.opts +4 -0
- metadata +102 -0
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
|
4
|
+
Dir.chdir File.dirname(__FILE__)
|
5
|
+
|
6
|
+
# Specs
|
7
|
+
task :default => :spec
|
8
|
+
|
9
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
10
|
+
t.spec_files = FileList["spec/**/*_spec.rb"].select{|f| f !~ /\/_/}
|
11
|
+
t.libs = ['lib'].collect{|f| "#{File.dirname __FILE__}/#{f}"}
|
12
|
+
end
|
13
|
+
|
14
|
+
# Gem
|
15
|
+
require 'rake/clean'
|
16
|
+
require 'rake/gempackagetask'
|
17
|
+
require 'fileutils'
|
18
|
+
|
19
|
+
spec = Gem::Specification.new do |s|
|
20
|
+
s.name = "mongo_mapper_ext"
|
21
|
+
s.version = "0.0.1"
|
22
|
+
s.summary = "Extensions for MongoMapper"
|
23
|
+
s.description = "Extensions for MongoMapper"
|
24
|
+
s.author = "Alexey Petrushin"
|
25
|
+
# s.email = ""
|
26
|
+
s.homepage = "http://github.com/alexeypetrushin/mongo_mapper_ext"
|
27
|
+
|
28
|
+
s.platform = Gem::Platform::RUBY
|
29
|
+
s.has_rdoc = true
|
30
|
+
# s.extra_rdoc_files = ["README.rdoc"]
|
31
|
+
|
32
|
+
# s.files = (%w{rakefile readme.md .gitignore} + Dir.glob("{app,lib,spec,.git}/**/*"))
|
33
|
+
s.files = (['Rakefile', 'readme.md'] + Dir.glob("{lib,spec}/**/*"))
|
34
|
+
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
|
37
|
+
warn 'uncomment ruby_ext'
|
38
|
+
[
|
39
|
+
# 'ruby_ext',
|
40
|
+
'mongo_mapper',
|
41
|
+
].each{|name| s.add_dependency(name)}
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
PACKAGE_DIR = "#{File.expand_path File.dirname(__FILE__)}/build"
|
46
|
+
|
47
|
+
Rake::GemPackageTask.new(spec) do |p|
|
48
|
+
package_dir = PACKAGE_DIR
|
49
|
+
# FileUtils.mkdir package_dir unless File.exist? package_dir
|
50
|
+
p.need_tar = true if RUBY_PLATFORM !~ /mswin/
|
51
|
+
p.need_zip = true
|
52
|
+
p.package_dir = package_dir
|
53
|
+
end
|
54
|
+
|
55
|
+
# CLEAN.include [ 'pkg', '*.gem']
|
56
|
+
|
57
|
+
task :push do
|
58
|
+
dir = Dir.chdir PACKAGE_DIR do
|
59
|
+
gem_file = Dir.glob("mongo_mapper_ext*.gem").first
|
60
|
+
system "gem push #{gem_file}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
task :clean do
|
65
|
+
system "rm -r #{PACKAGE_DIR}"
|
66
|
+
end
|
67
|
+
|
68
|
+
task :release => [:gem, :push, :clean]
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
class ConnectionsPool < Hash
|
3
|
+
def [](database_alias)
|
4
|
+
database_alias = database_alias.to_s
|
5
|
+
unless connection = super(database_alias)
|
6
|
+
MongoMapper.db_config.must.include database_alias
|
7
|
+
db_options = MongoMapper.db_config[database_alias]
|
8
|
+
connection = Mongo::Connection.new(db_options['host'], db_options['port'], :logger => MongoMapper.logger)
|
9
|
+
|
10
|
+
if defined?(PhusionPassenger)
|
11
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
12
|
+
connection.connect_to_master if forked
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
self[database_alias] = connection
|
17
|
+
end
|
18
|
+
return connection
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class DatabasesPool < Hash
|
23
|
+
def [](database_alias)
|
24
|
+
database_alias = database_alias.to_s
|
25
|
+
unless db = super(database_alias)
|
26
|
+
MongoMapper.db_config.must.include database_alias
|
27
|
+
db_options = MongoMapper.db_config[database_alias]
|
28
|
+
db = MongoMapper.connections[database_alias].db db_options['name'].must_be.a(String)
|
29
|
+
self[database_alias] = db
|
30
|
+
end
|
31
|
+
return db
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
36
|
+
attr_accessor :db_config
|
37
|
+
|
38
|
+
def db_config
|
39
|
+
# unless @db_config
|
40
|
+
#
|
41
|
+
# if defined?(::Rails) and defined?(DATABASE)
|
42
|
+
# @db_config = {}
|
43
|
+
# DATABASE["#{::Rails.env}!"].to_h.each do |db_alias, options|
|
44
|
+
# @db_config[db_alias.to_s] = {
|
45
|
+
# 'name' => options.name!,
|
46
|
+
# 'host' => options.host(nil),
|
47
|
+
# 'port' => options.port(nil)
|
48
|
+
# }
|
49
|
+
# end
|
50
|
+
# else
|
51
|
+
# @db_config = {}
|
52
|
+
# # raise "If you don't using Rails you must override this method and provide your own config!"
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
@db_config ||= {}
|
56
|
+
end
|
57
|
+
|
58
|
+
def connections
|
59
|
+
@connections ||= ConnectionsPool.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def databases
|
63
|
+
@databases ||= DatabasesPool.new
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# ObjectID
|
3
|
+
#
|
4
|
+
# Mongo::ObjectID.class_eval do
|
5
|
+
# def == other
|
6
|
+
# self.to_s == other.to_s
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# def to_yaml *args
|
10
|
+
# to_s.to_yaml *args
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
|
14
|
+
MongoMapper::Plugins::Associations::InArrayProxy.class_eval do
|
15
|
+
def delete(doc)
|
16
|
+
ids.delete(doc.id)
|
17
|
+
klass.delete(doc.id)
|
18
|
+
reset
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Measures MongoDB requests time and adds it to log
|
2
|
+
|
3
|
+
if defined?(Rails) and RAILS_ENV == 'development'
|
4
|
+
Mongo::Connection.class_eval do
|
5
|
+
def send_message_with_time operation, message, log_message=nil
|
6
|
+
begin
|
7
|
+
logger = @logger
|
8
|
+
@logger = nil
|
9
|
+
t = Time.now
|
10
|
+
send_message_without_time operation, message, log_message
|
11
|
+
ensure
|
12
|
+
logger.debug(" MONGODB (#{Time.now - t}) #{log_message || message}") if logger
|
13
|
+
@logger = logger
|
14
|
+
end
|
15
|
+
end
|
16
|
+
alias_method_chain :send_message, :time
|
17
|
+
|
18
|
+
def send_message_with_safe_check_with_time operation, message, db_name, log_message=nil
|
19
|
+
begin
|
20
|
+
logger = @logger
|
21
|
+
@logger = nil
|
22
|
+
t = Time.now
|
23
|
+
send_message_with_safe_check_without_time operation, message, db_name, log_message
|
24
|
+
ensure
|
25
|
+
logger.debug(" MONGODB (#{Time.now - t}) #{log_message || message}") if logger
|
26
|
+
@logger = logger
|
27
|
+
end
|
28
|
+
end
|
29
|
+
alias_method_chain :send_message_with_safe_check, :time
|
30
|
+
|
31
|
+
def receive_message_with_time operation, message, log_message=nil, socket=nil
|
32
|
+
begin
|
33
|
+
logger = @logger
|
34
|
+
@logger = nil
|
35
|
+
t = Time.now
|
36
|
+
receive_message_without_time operation, message, log_message, socket
|
37
|
+
ensure
|
38
|
+
logger.debug(" MONGODB (#{Time.now - t}) #{log_message || message}") if logger
|
39
|
+
@logger = logger
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias_method_chain :receive_message, :time
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#
|
2
|
+
# upsert
|
3
|
+
#
|
4
|
+
Mongo::Collection.class_eval do
|
5
|
+
def upsert id, opt
|
6
|
+
opt.size.must == 1
|
7
|
+
opt.must_be.a Hash
|
8
|
+
opt.values.first.must_be.a Hash
|
9
|
+
|
10
|
+
update({:_id => id}, opt, {:upsert => true, :safe => true})
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
#
|
16
|
+
# silence logging
|
17
|
+
#
|
18
|
+
Mongo::Connection.class_eval do
|
19
|
+
attr_writer :logger
|
20
|
+
end
|
21
|
+
|
22
|
+
MongoMapper.class_eval do
|
23
|
+
def self.temporary_silince_logger &block
|
24
|
+
logger, nil_logger = self.logger, Logger.new(nil)
|
25
|
+
|
26
|
+
begin
|
27
|
+
MongoMapper.logger = nil_logger
|
28
|
+
connections.each do |name, connection|
|
29
|
+
connection.logger = nil_logger
|
30
|
+
end
|
31
|
+
block.call
|
32
|
+
ensure
|
33
|
+
MongoMapper.logger = logger
|
34
|
+
connections.each do |name, connection|
|
35
|
+
connection.logger = logger
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
#
|
43
|
+
# Silence index creation
|
44
|
+
#
|
45
|
+
MongoMapper::Plugins::Indexes::ClassMethods.class_eval do
|
46
|
+
def ensure_index_with_silent_logger *args
|
47
|
+
MongoMapper.temporary_silince_logger do
|
48
|
+
ensure_index_without_silent_logger *args
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
alias_method_chain :ensure_index, :silent_logger
|
53
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
Rake::TaskManager.class_eval do
|
2
|
+
def remove_task(task_name)
|
3
|
+
@tasks.delete(task_name.to_s)
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
def remove_task(task_name)
|
8
|
+
Rake.application.remove_task(task_name)
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :db do
|
12
|
+
|
13
|
+
remove_task 'db:migrate'
|
14
|
+
desc "Migrate Database"
|
15
|
+
task :migrate => :environment do
|
16
|
+
::Migration = MongoMapper::Migration
|
17
|
+
Dir["#{Rails.root}/lib/db/**/*.rb"].each{|f| require f.sub(/\.rb$/, '')}
|
18
|
+
|
19
|
+
database_alias = ENV['d'] || ENV['database']
|
20
|
+
database_alias = 'accounts' if database_alias.blank?
|
21
|
+
|
22
|
+
version = ENV['v'] || ENV['version']
|
23
|
+
if version.blank?
|
24
|
+
size = MongoMapper::Migration.definitions[database_alias].size
|
25
|
+
highest_defined_version = size == 0 ? 0 : size - 1
|
26
|
+
version = highest_defined_version
|
27
|
+
else
|
28
|
+
version = version.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
MongoMapper::Migration.update database_alias, version
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module MongoMapper::Migration
|
2
|
+
class MigrationDefinition
|
3
|
+
def upgrade &block
|
4
|
+
if block
|
5
|
+
@upgrade = block
|
6
|
+
else
|
7
|
+
@upgrade
|
8
|
+
end
|
9
|
+
end
|
10
|
+
alias_method :up, :upgrade
|
11
|
+
|
12
|
+
def downgrade &block
|
13
|
+
if block
|
14
|
+
@downgrade = block
|
15
|
+
else
|
16
|
+
@downgrade
|
17
|
+
end
|
18
|
+
end
|
19
|
+
alias_method :down, :downgrade
|
20
|
+
end
|
21
|
+
|
22
|
+
class Logger
|
23
|
+
attr_accessor :enabled
|
24
|
+
|
25
|
+
def initialize enabled = true
|
26
|
+
self.enabled = enabled
|
27
|
+
end
|
28
|
+
|
29
|
+
def info message
|
30
|
+
puts message if enabled
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
def logger= logger
|
36
|
+
@logger = logger ? logger : Logger.new(false)
|
37
|
+
end
|
38
|
+
|
39
|
+
def logger; @logger ||= Logger.new end
|
40
|
+
|
41
|
+
def define database_alias, version, &block
|
42
|
+
database_alias = database_alias.to_s
|
43
|
+
|
44
|
+
version.must_be.a Integer
|
45
|
+
definition = MigrationDefinition.new
|
46
|
+
block.call definition
|
47
|
+
definitions[database_alias][version] = definition
|
48
|
+
end
|
49
|
+
|
50
|
+
def update database_alias, version
|
51
|
+
database_alias = database_alias.to_s
|
52
|
+
db = MongoMapper.databases[database_alias]
|
53
|
+
|
54
|
+
if metadata(db).version == version
|
55
|
+
logger.info "Database '#{database_alias}' already is of #{version} version, no migration needed."
|
56
|
+
return false
|
57
|
+
else
|
58
|
+
logger.info "Migration for '#{database_alias}' Database:"
|
59
|
+
end
|
60
|
+
|
61
|
+
increase_db_version database_alias, db while metadata(db).version < version
|
62
|
+
decrease_db_version database_alias, db while metadata(db).version > version
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
def metadata db
|
67
|
+
col = db.collection 'db_metadata'
|
68
|
+
metadata = (col.find_one || {:version => 0}).to_openobject
|
69
|
+
end
|
70
|
+
|
71
|
+
def definitions
|
72
|
+
@definitions ||= Hash.new{|h, k| h[k] = []}
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
def increase_db_version database_alias, db
|
77
|
+
m = metadata(db)
|
78
|
+
migration = definitions[database_alias][m.version + 1]
|
79
|
+
raise "No upgrade for version #{m.version + 1} of '#{database_alias}' Database!" unless migration and migration.up
|
80
|
+
|
81
|
+
migration.up.call db
|
82
|
+
|
83
|
+
m.version += 1
|
84
|
+
update_metadata db, m
|
85
|
+
|
86
|
+
logger.info "Database '#{database_alias}' upgraded to version #{m.version}."
|
87
|
+
end
|
88
|
+
|
89
|
+
def decrease_db_version database_alias, db
|
90
|
+
m = metadata(db)
|
91
|
+
migration = definitions[database_alias][m.version]
|
92
|
+
raise "No downgrade for version #{m.version} of '#{database_alias}' Database!" unless migration and migration.down
|
93
|
+
|
94
|
+
migration.down.call db
|
95
|
+
|
96
|
+
m.version -= 1
|
97
|
+
update_metadata db, m
|
98
|
+
|
99
|
+
logger.info "Database '#{database_alias}' downgraded to version #{m.version}."
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def update_metadata db, metadata
|
104
|
+
col = db.collection 'db_metadata'
|
105
|
+
col.save metadata.to_hash
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
MongoMapper.class_eval do
|
2
|
+
class << self
|
3
|
+
|
4
|
+
def logger
|
5
|
+
# return @logger ||= Logger.new(nil) if defined?(Spec)
|
6
|
+
unless @logger
|
7
|
+
@logger = if "irb" == $0
|
8
|
+
Logger.new(STDOUT)
|
9
|
+
else
|
10
|
+
if defined?(Rails)
|
11
|
+
Rails.test? ? Logger.new(nil) : Rails.logger
|
12
|
+
else
|
13
|
+
Logger.new(STDOUT)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
@logger
|
18
|
+
end
|
19
|
+
|
20
|
+
def logger= logger
|
21
|
+
@logger = logger
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
module Plugins
|
3
|
+
module AttributesCache
|
4
|
+
|
5
|
+
module InstanceMethods
|
6
|
+
def cache
|
7
|
+
@cache ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def clear_cache
|
11
|
+
@cache = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def reload
|
15
|
+
@cache.clear if @cache
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# #
|
2
|
+
# # Connect to database_alias specified in config
|
3
|
+
# #
|
4
|
+
# module MongoMapper
|
5
|
+
# module Plugins
|
6
|
+
# module DbConfig
|
7
|
+
#
|
8
|
+
# module ClassMethods
|
9
|
+
# inheritable_accessor :database_alias, nil
|
10
|
+
# def use_database database_alias
|
11
|
+
# self.database_alias = database_alias.to_s
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def connection(mongo_connection=nil)
|
15
|
+
# assert_supported
|
16
|
+
# if mongo_connection.nil?
|
17
|
+
# @connection || connection_from_alias || MongoMapper.connection
|
18
|
+
# else
|
19
|
+
# @connection = mongo_connection
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def database_name
|
24
|
+
# assert_supported
|
25
|
+
# @database_name || database_name_from_alias
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# private
|
29
|
+
# def database_name_from_alias
|
30
|
+
# return unless database_alias
|
31
|
+
#
|
32
|
+
# MongoMapper.db_config.must.include database_alias
|
33
|
+
# MongoMapper.db_config[database_alias]['name']
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# def connection_from_alias
|
37
|
+
# return unless database_alias
|
38
|
+
#
|
39
|
+
# MongoMapper.db_config.must.include database_alias
|
40
|
+
# MongoMapper.connections[database_alias]
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
# end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
module Plugins
|
3
|
+
module DefaultScope
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def query options = {}
|
7
|
+
super default_scope_options.merge(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def find_one options = {}
|
11
|
+
super default_scope_options.merge(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_many options = {}
|
15
|
+
super default_scope_options.merge(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def count options={}
|
19
|
+
super default_scope_options.merge(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def with_exclusive_scope options = {}, &block
|
23
|
+
Thread.current['mm_with_exclusive_scope'].must_be.nil
|
24
|
+
|
25
|
+
before = Thread.current['mm_with_exclusive_scope']
|
26
|
+
begin
|
27
|
+
Thread.current['mm_with_exclusive_scope'] = options
|
28
|
+
block.call if block
|
29
|
+
ensure
|
30
|
+
Thread.current['mm_with_exclusive_scope'] = before
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_scope options = {}, &block
|
35
|
+
Thread.current['mm_with_exclusive_scope'].must_be.nil
|
36
|
+
|
37
|
+
before = Thread.current['mm_with_scope']
|
38
|
+
begin
|
39
|
+
options = before.merge options if before
|
40
|
+
Thread.current['mm_with_scope'] = options
|
41
|
+
block.call if block
|
42
|
+
ensure
|
43
|
+
Thread.current['mm_with_scope'] = before
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
def default_scope options = nil, &block
|
49
|
+
options.must_be.a [NilClass, Hash]
|
50
|
+
self.write_inheritable_attribute(:default_scope, (options || block))
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def default_scope_options
|
55
|
+
default_scope = self.read_inheritable_attribute(:default_scope)
|
56
|
+
|
57
|
+
exclusive_options = Thread.current['mm_with_exclusive_scope']
|
58
|
+
return exclusive_options if exclusive_options
|
59
|
+
|
60
|
+
options = if default_scope
|
61
|
+
if default_scope.respond_to? :call
|
62
|
+
default_scope.call self
|
63
|
+
else
|
64
|
+
default_scope
|
65
|
+
end
|
66
|
+
else
|
67
|
+
{}
|
68
|
+
end
|
69
|
+
|
70
|
+
if scope_options = Thread.current['mm_with_scope']
|
71
|
+
options = options.merge scope_options
|
72
|
+
end
|
73
|
+
|
74
|
+
options
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
# def self.deferred; @deferred ||= [] end
|
3
|
+
# def self.call_deferred
|
4
|
+
# deferred.every.call
|
5
|
+
# deferred.clear
|
6
|
+
# end
|
7
|
+
|
8
|
+
module Plugins
|
9
|
+
module Micelaneous
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
def upsert *args
|
13
|
+
self.class.upsert id, *args
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
#
|
19
|
+
# Sequentiall :all for big collection
|
20
|
+
#
|
21
|
+
def all_sequentially &block
|
22
|
+
page, per_page = 1, 5
|
23
|
+
begin
|
24
|
+
results = paginate(:page => page, :per_page => per_page, :order => '_id asc')
|
25
|
+
results.each{|o| block.call o}
|
26
|
+
page += 1
|
27
|
+
end until results.blank? or results.size < per_page
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
#
|
32
|
+
# Deferred execution
|
33
|
+
#
|
34
|
+
# def defer &block
|
35
|
+
# MongoMapper.deferred << block
|
36
|
+
# end
|
37
|
+
|
38
|
+
|
39
|
+
#
|
40
|
+
# Connect to database_alias specified in config
|
41
|
+
#
|
42
|
+
def use_database database_alias
|
43
|
+
# defer do
|
44
|
+
database_alias = database_alias.to_s
|
45
|
+
MongoMapper.db_config.must.include database_alias
|
46
|
+
|
47
|
+
self.connection MongoMapper.connections[database_alias]
|
48
|
+
set_database_name MongoMapper.db_config[database_alias]['name']
|
49
|
+
# end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
#
|
54
|
+
# shortcut for upsert
|
55
|
+
#
|
56
|
+
def upsert *args
|
57
|
+
collection.upsert *args
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
#
|
62
|
+
# CounterCache
|
63
|
+
# belongs_to :item, :counter_cashe => true
|
64
|
+
#
|
65
|
+
def belongs_to association_id, options={}, &extension
|
66
|
+
options.must_not.include :counter_cashe
|
67
|
+
if options.delete(:counter_cache) || options.delete('counter_cache')
|
68
|
+
association_id = association_id.to_s
|
69
|
+
association_key = "#{association_id}_id"
|
70
|
+
cache_attribute = "#{name.pluralize.underscore}_count"
|
71
|
+
cache_class = association_id.classify.constantize
|
72
|
+
cache_class.keys.must.include cache_attribute
|
73
|
+
increase_method_name = "increase_#{cache_class.name.underscore}_#{name.pluralize.underscore}_counter"
|
74
|
+
decrease_method_name = "decrease_#{cache_class.name.underscore}_#{name.pluralize.underscore}_counter"
|
75
|
+
|
76
|
+
define_method increase_method_name do
|
77
|
+
cache_class.upsert self.send(association_key), :$inc => {cache_attribute => 1}
|
78
|
+
end
|
79
|
+
protected increase_method_name
|
80
|
+
|
81
|
+
define_method decrease_method_name do
|
82
|
+
cache_class.upsert self.send(association_key), :$inc => {cache_attribute => -1}
|
83
|
+
end
|
84
|
+
protected decrease_method_name
|
85
|
+
|
86
|
+
after_create increase_method_name
|
87
|
+
after_destroy decrease_method_name
|
88
|
+
end
|
89
|
+
|
90
|
+
super association_id, options, &extension
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# Disabling indexes in test environment
|
3
|
+
#
|
4
|
+
# if Object.const_defined?(:RAILS_ENV) and Object.const_get(:RAILS_ENV) != 'production'
|
5
|
+
# MongoMapper::Plugins::Indexes::ClassMethods.class_eval do
|
6
|
+
# def ensure_index(name_or_array, options={})
|
7
|
+
# end
|
8
|
+
# end
|
9
|
+
# end
|
10
|
+
|
11
|
+
if Object.const_defined?(:Crystal) and Crystal.respond_to?(:run)
|
12
|
+
MongoMapper::Plugins::Indexes::ClassMethods.class_eval do
|
13
|
+
alias_method :original_ensure_index, :ensure_index
|
14
|
+
def ensure_index_stub *args; end
|
15
|
+
end
|
16
|
+
|
17
|
+
crystal.after :config do |config|
|
18
|
+
if config.production?
|
19
|
+
MongoMapper::Plugins::Indexes::ClassMethods.send :alias_method, :ensure_index, :original_ensure_index
|
20
|
+
else
|
21
|
+
MongoMapper::Plugins::Indexes::ClassMethods.send :alias_method, :ensure_index, :ensure_index_stub
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
#
|
28
|
+
# Clear db before each test
|
29
|
+
#
|
30
|
+
Spec::Example::ExampleGroup.class_eval do
|
31
|
+
class << self
|
32
|
+
def with_mongo_mapper
|
33
|
+
before :each do
|
34
|
+
MongoMapper.db_config.each do |db_alias, opt|
|
35
|
+
db = MongoMapper.databases[db_alias]
|
36
|
+
db.collection_names.each do |name|
|
37
|
+
next if name =~ /^system\./
|
38
|
+
db.collection(name).drop
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
# Spec::Runner.configure do |config|
|
46
|
+
# config.before(:each) do
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
|
50
|
+
|
51
|
+
#
|
52
|
+
# Silence logger
|
53
|
+
#
|
54
|
+
MongoMapper.logger = Logger.new(nil)
|
55
|
+
if defined? Paperclip
|
56
|
+
Paperclip.class_eval do
|
57
|
+
def self.logger
|
58
|
+
@logger ||= Logger.new(nil)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
gem 'mongo_mapper', '>=0.8'
|
2
|
+
require 'mongo_mapper'
|
3
|
+
|
4
|
+
|
5
|
+
[
|
6
|
+
'hacks/fixes',
|
7
|
+
'hacks/time_measuring',
|
8
|
+
'migration',
|
9
|
+
'mongo_mapper',
|
10
|
+
'view_helpers',
|
11
|
+
'db_config',
|
12
|
+
'micelaneous',
|
13
|
+
|
14
|
+
'plugins/default_scope',
|
15
|
+
# 'plugins/db_config',
|
16
|
+
'plugins/attributes_cache',
|
17
|
+
'plugins/micelaneous',
|
18
|
+
].each do |file|
|
19
|
+
require "mongo_mapper_ext/#{file}"
|
20
|
+
end
|
21
|
+
|
22
|
+
module CommonPluginsAddition
|
23
|
+
def self.included(model)
|
24
|
+
model.plugin MongoMapper::Plugins::DefaultScope
|
25
|
+
# model.plugin MongoMapper::Plugins::DbConfig
|
26
|
+
model.plugin MongoMapper::Plugins::AttributesCache
|
27
|
+
model.plugin MongoMapper::Plugins::Micelaneous
|
28
|
+
|
29
|
+
model.attr_protected :id, :_id, :_type, :created_at, :updated_at
|
30
|
+
end
|
31
|
+
end
|
32
|
+
MongoMapper::Document.append_inclusions(CommonPluginsAddition)
|
data/readme.md
ADDED
data/spec/helper.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require "#{File.expand_path(File.dirname(__FILE__))}/helper"
|
2
|
+
|
3
|
+
require "mongo_mapper_ext/micelaneous"
|
4
|
+
require "mongo_mapper_ext/plugins/micelaneous"
|
5
|
+
|
6
|
+
describe "MongoMapper Default Scope" do
|
7
|
+
|
8
|
+
before :all do
|
9
|
+
class ::Post
|
10
|
+
include MongoMapper::Document
|
11
|
+
plugin MongoMapper::Plugins::Micelaneous
|
12
|
+
|
13
|
+
key :comments_count, Integer, :default => 0
|
14
|
+
has_many :comments
|
15
|
+
end
|
16
|
+
|
17
|
+
class ::Comment
|
18
|
+
include MongoMapper::Document
|
19
|
+
plugin MongoMapper::Plugins::Micelaneous
|
20
|
+
|
21
|
+
key :post_id
|
22
|
+
belongs_to :post, :counter_cache => true
|
23
|
+
end
|
24
|
+
|
25
|
+
MongoMapper.database = 'test'
|
26
|
+
end
|
27
|
+
|
28
|
+
after :all do
|
29
|
+
%w{Post Comment}.each do |obj_name|
|
30
|
+
Object.send :remove_const, obj_name if Object.const_defined? obj_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
before :each do
|
35
|
+
[Post, Comment].every.delete_all
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should increase count of comments" do
|
39
|
+
post = Post.create!
|
40
|
+
comment = post.comments.create!
|
41
|
+
|
42
|
+
post.reload
|
43
|
+
post.comments_count.should == 1
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should decrease count of comments" do
|
47
|
+
post = Post.create!
|
48
|
+
comment = post.comments.create!
|
49
|
+
post.reload
|
50
|
+
post.comments_count.should == 1
|
51
|
+
|
52
|
+
comment.destroy
|
53
|
+
post.reload
|
54
|
+
post.comments_count.should == 0
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "#{File.expand_path(File.dirname(__FILE__))}/helper"
|
2
|
+
|
3
|
+
require "mongo_mapper_ext/micelaneous"
|
4
|
+
require "mongo_mapper_ext/plugins/micelaneous"
|
5
|
+
|
6
|
+
describe "MongoMapper micelaneous" do
|
7
|
+
before :all do
|
8
|
+
@db = Mongo::Connection.new.db('test')
|
9
|
+
MongoMapper.database = 'test'
|
10
|
+
end
|
11
|
+
|
12
|
+
before :each do
|
13
|
+
@db.collection('test').drop
|
14
|
+
@coll = @db.collection('test')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "upsert should update" do
|
18
|
+
id = @coll.save :count => 2
|
19
|
+
@coll.upsert id, :$inc => {:count => 1}
|
20
|
+
@coll.find(:_id => id).first['count'].should == 3
|
21
|
+
end
|
22
|
+
|
23
|
+
it "upsert should set" do
|
24
|
+
id = @coll.save({})
|
25
|
+
@coll.upsert id, :$inc => {:count => 1}
|
26
|
+
@coll.find(:_id => id).first['count'].should == 1
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "handy upsert" do
|
30
|
+
class ::UpsertSample
|
31
|
+
include MongoMapper::Document
|
32
|
+
plugin MongoMapper::Plugins::Micelaneous
|
33
|
+
|
34
|
+
key :counter, Integer, :default => 1
|
35
|
+
end
|
36
|
+
|
37
|
+
before :each do
|
38
|
+
@model = UpsertSample.create!
|
39
|
+
end
|
40
|
+
|
41
|
+
it "class upsert" do
|
42
|
+
UpsertSample.upsert @model.id, :$inc => {:counter => 1}
|
43
|
+
@model.reload
|
44
|
+
@model.counter.should == 2
|
45
|
+
end
|
46
|
+
|
47
|
+
it "model upsert" do
|
48
|
+
@model.upsert :$inc => {:counter => 1}
|
49
|
+
@model.reload
|
50
|
+
@model.counter.should == 2
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "#{File.expand_path(File.dirname(__FILE__))}/helper"
|
2
|
+
|
3
|
+
require "mongo_mapper_ext"
|
4
|
+
require "mongo_mapper_ext/spec/helper"
|
5
|
+
|
6
|
+
describe "MongoMapper Migration" do
|
7
|
+
with_mongo_mapper
|
8
|
+
|
9
|
+
Migration = MongoMapper::Migration
|
10
|
+
|
11
|
+
before :all do
|
12
|
+
MongoMapper.logger = Logger.new(nil)
|
13
|
+
MongoMapper.db_config = {
|
14
|
+
'global' => {'name' => 'global_test'},
|
15
|
+
'accounts' => {'name' => "accounts_test"}
|
16
|
+
}
|
17
|
+
|
18
|
+
class ::Sample
|
19
|
+
include MongoMapper::Document
|
20
|
+
use_database :global
|
21
|
+
|
22
|
+
key :name, String
|
23
|
+
end
|
24
|
+
|
25
|
+
# MongoMapper.call_deferred
|
26
|
+
Migration.logger = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
after :all do
|
30
|
+
Object.send :remove_const, :Sample if Object.const_defined? :Sample
|
31
|
+
end
|
32
|
+
|
33
|
+
before :each do
|
34
|
+
Migration.definitions.clear
|
35
|
+
end
|
36
|
+
|
37
|
+
it "Shouldn't update if versions are the same" do
|
38
|
+
Migration.update(:global, 0).should be_false
|
39
|
+
end
|
40
|
+
|
41
|
+
it "migration should provide access to current database" do
|
42
|
+
Sample.count.should == 0
|
43
|
+
Migration.define :global, 1 do |m|
|
44
|
+
m.up do |db|
|
45
|
+
Sample.create :name => 'name'
|
46
|
+
coll = db.collection 'samples'
|
47
|
+
coll.find.count.should == 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
Migration.update(:global, 1).should be_true
|
52
|
+
Sample.count.should == 1
|
53
|
+
end
|
54
|
+
|
55
|
+
it "increase_db_version" do
|
56
|
+
Sample.count.should == 0
|
57
|
+
Migration.define :global, 1 do |m|
|
58
|
+
m.up{Sample.create :name => 'name'}
|
59
|
+
end
|
60
|
+
|
61
|
+
Migration.update(:global, 1).should be_true
|
62
|
+
Sample.count.should == 1
|
63
|
+
Migration.metadata(MongoMapper.databases[:global]).version.should == 1
|
64
|
+
end
|
65
|
+
|
66
|
+
it "decrease_db_version" do
|
67
|
+
Migration.define :global, 1 do |m|
|
68
|
+
m.up{Sample.create :name => 'name'}
|
69
|
+
m.down{Sample.destroy_all}
|
70
|
+
end
|
71
|
+
Migration.update(:global, 1).should be_true
|
72
|
+
Sample.count.should == 1
|
73
|
+
|
74
|
+
Migration.update(:global, 0).should be_true
|
75
|
+
Sample.count.should == 0
|
76
|
+
Migration.metadata(MongoMapper.databases[:global]).version.should == 0
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/spec/mm_spec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'mongo_mapper'
|
2
|
+
|
3
|
+
describe "Special test to check some errors in the MongoMapper itself" do
|
4
|
+
before :all do
|
5
|
+
MongoMapper.database = 'test'
|
6
|
+
|
7
|
+
class ::AnObject
|
8
|
+
include MongoMapper::Document
|
9
|
+
|
10
|
+
key :owner_name, String
|
11
|
+
key :viewers, Array
|
12
|
+
|
13
|
+
def owner_name= owner_name
|
14
|
+
viewers.delete self.owner_name
|
15
|
+
viewers << owner_name
|
16
|
+
# write_attribute :owner_name, owner_name
|
17
|
+
super owner_name
|
18
|
+
owner_name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
after :all do
|
24
|
+
Object.send :remove_const, :AnObject if Object.const_defined? :AnObject
|
25
|
+
end
|
26
|
+
|
27
|
+
it do
|
28
|
+
o = AnObject.new
|
29
|
+
o.owner_name = 'user'
|
30
|
+
o.save!
|
31
|
+
|
32
|
+
# o = AnObject.first # don't use reload, it willn't catch this error
|
33
|
+
o.viewers.should == %w{user}
|
34
|
+
end
|
35
|
+
end
|
data/spec/scope_spec.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
require "#{File.expand_path(File.dirname(__FILE__))}/helper"
|
2
|
+
|
3
|
+
require "mongo_mapper_ext/plugins/default_scope"
|
4
|
+
|
5
|
+
describe "MongoMapper Default Scope" do
|
6
|
+
before :all do
|
7
|
+
MongoMapper.database = 'test'
|
8
|
+
end
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
class ::ScopeSample
|
12
|
+
include MongoMapper::Document
|
13
|
+
plugin MongoMapper::Plugins::DefaultScope
|
14
|
+
|
15
|
+
key :name, String
|
16
|
+
key :_type, String
|
17
|
+
end
|
18
|
+
|
19
|
+
ScopeSample.delete_all
|
20
|
+
ScopeSample.create! :name => 'a'
|
21
|
+
ScopeSample.create! :name => 'b'
|
22
|
+
end
|
23
|
+
|
24
|
+
after :each do
|
25
|
+
Object.send :remove_const, :ScopeSample if Object.const_defined? :ScopeSample
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not affect objects without default_scope" do
|
29
|
+
ScopeSample.count.should == 2
|
30
|
+
ScopeSample.all.count.should == 2
|
31
|
+
end
|
32
|
+
|
33
|
+
it "default_scope" do
|
34
|
+
ScopeSample.send :default_scope, :name => 'a'
|
35
|
+
ScopeSample.count.should == 1
|
36
|
+
ScopeSample.all.count.should == 1
|
37
|
+
ScopeSample.first.name.should == 'a'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "default_scope as block" do
|
41
|
+
ScopeSample.send :default_scope do
|
42
|
+
{:name => 'a'}
|
43
|
+
end
|
44
|
+
ScopeSample.count.should == 1
|
45
|
+
ScopeSample.all.count.should == 1
|
46
|
+
ScopeSample.first.name.should == 'a'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "default_scope should be inherited" do
|
50
|
+
ScopeSample.send :default_scope, :name => 'a'
|
51
|
+
class ScopeSampleAncestor < ScopeSample
|
52
|
+
end
|
53
|
+
|
54
|
+
ScopeSampleAncestor.create! :name => 'a'
|
55
|
+
ScopeSampleAncestor.create! :name => 'b'
|
56
|
+
|
57
|
+
ScopeSampleAncestor.count.should == 1
|
58
|
+
ScopeSampleAncestor.all.count.should == 1
|
59
|
+
ScopeSampleAncestor.first.name.should == 'a'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "ancestors should be able to override default_scope" do
|
63
|
+
ScopeSample.send :default_scope, :name => 'a'
|
64
|
+
class ScopeSampleAncestor2 < ScopeSample
|
65
|
+
default_scope :name => 'b'
|
66
|
+
end
|
67
|
+
|
68
|
+
ScopeSampleAncestor2.create! :name => 'a'
|
69
|
+
ScopeSampleAncestor2.create! :name => 'b'
|
70
|
+
|
71
|
+
ScopeSampleAncestor2.count.should == 1
|
72
|
+
ScopeSampleAncestor2.all.count.should == 1
|
73
|
+
ScopeSampleAncestor2.first.name.should == 'b'
|
74
|
+
end
|
75
|
+
|
76
|
+
it "shouldn't allow to nest with_exclusive_scope" do
|
77
|
+
lambda{
|
78
|
+
ScopeSample.with_exclusive_scope do
|
79
|
+
ScopeSample.with_exclusive_scope{}
|
80
|
+
end
|
81
|
+
}.should raise_error(AssertionError)
|
82
|
+
|
83
|
+
lambda{
|
84
|
+
ScopeSample.with_exclusive_scope do
|
85
|
+
ScopeSample.with_scope{}
|
86
|
+
end
|
87
|
+
}.should raise_error(AssertionError)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "with_exclusive_scope should clear other scopes" do
|
91
|
+
ScopeSample.send :default_scope, :name => 'a'
|
92
|
+
|
93
|
+
ScopeSample.with_scope :name => 'a' do
|
94
|
+
ScopeSample.with_exclusive_scope :name => 'b' do
|
95
|
+
ScopeSample.count.should == 1
|
96
|
+
ScopeSample.first.name.should == 'b'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "with_scope" do
|
102
|
+
ScopeSample.with_scope :name => 'a' do
|
103
|
+
ScopeSample.count.should == 1
|
104
|
+
ScopeSample.first.name.should == 'a'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it "with scope should merge scope" do
|
109
|
+
ScopeSample.class_eval do
|
110
|
+
key :name2, String
|
111
|
+
key :name3, String
|
112
|
+
default_scope :name => 'a'
|
113
|
+
end
|
114
|
+
ScopeSample.create! :name => 'a', :name2 => 'a2', :name3 => 'a3'
|
115
|
+
ScopeSample.create! :name => 'b', :name2 => 'b2', :name3 => 'b3'
|
116
|
+
|
117
|
+
ScopeSample.with_scope :name2 => 'a2' do
|
118
|
+
ScopeSample.with_scope :name3 => 'a3' do
|
119
|
+
ScopeSample.count.should == 1
|
120
|
+
ScopeSample.first.name2.should == 'a2'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/spec/spec.opts
ADDED
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongo_mapper_ext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Alexey Petrushin
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-11 00:00:00 +04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: mongo_mapper
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
description: Extensions for MongoMapper
|
36
|
+
email:
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- Rakefile
|
45
|
+
- readme.md
|
46
|
+
- lib/mongo_mapper_ext/db_config.rb
|
47
|
+
- lib/mongo_mapper_ext/hacks/fixes.rb
|
48
|
+
- lib/mongo_mapper_ext/hacks/time_measuring.rb
|
49
|
+
- lib/mongo_mapper_ext/micelaneous.rb
|
50
|
+
- lib/mongo_mapper_ext/migrate.rake
|
51
|
+
- lib/mongo_mapper_ext/migration.rb
|
52
|
+
- lib/mongo_mapper_ext/mongo_mapper.rb
|
53
|
+
- lib/mongo_mapper_ext/plugins/attributes_cache.rb
|
54
|
+
- lib/mongo_mapper_ext/plugins/db_config.rb
|
55
|
+
- lib/mongo_mapper_ext/plugins/default_scope.rb
|
56
|
+
- lib/mongo_mapper_ext/plugins/micelaneous.rb
|
57
|
+
- lib/mongo_mapper_ext/spec/helper.rb
|
58
|
+
- lib/mongo_mapper_ext/view_helpers.rb
|
59
|
+
- lib/mongo_mapper_ext.rb
|
60
|
+
- spec/helper.rb
|
61
|
+
- spec/micelaneous_plugin_spec.rb
|
62
|
+
- spec/micelaneous_spec.rb
|
63
|
+
- spec/migration_spec.rb
|
64
|
+
- spec/mm_spec.rb
|
65
|
+
- spec/scope_spec.rb
|
66
|
+
- spec/spec.opts
|
67
|
+
has_rdoc: true
|
68
|
+
homepage: http://github.com/alexeypetrushin/mongo_mapper_ext
|
69
|
+
licenses: []
|
70
|
+
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
requirements: []
|
95
|
+
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.3.7
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: Extensions for MongoMapper
|
101
|
+
test_files: []
|
102
|
+
|