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 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,10 @@
1
+ #
2
+ # HTML helpers
3
+ #
4
+ [MongoMapper::EmbeddedDocument, MongoMapper::Document].each do |aclass|
5
+ aclass.class_eval do
6
+ def dom_id
7
+ new_record? ? "new_#{self.class.name.underscore}" : to_param
8
+ end
9
+ end
10
+ 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
@@ -0,0 +1,3 @@
1
+ # Extensions for MongoMapper.
2
+
3
+ [add readme, for now go to specs]
data/spec/helper.rb ADDED
@@ -0,0 +1,8 @@
1
+ dir = File.expand_path(File.dirname(__FILE__))
2
+ lib_dir = File.expand_path("#{dir}/../../../lib")
3
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include? lib_dir
4
+
5
+ require 'spec_ext'
6
+ gem 'mongo_mapper', '>=0.8'
7
+ require "mongo_mapper"
8
+ require 'ruby_ext'
@@ -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
@@ -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
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
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
+