mongo_mapper_ext 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|