mongoid_misc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +10 -0
- data/lib/carrierwave_ext/fixes.rb +12 -0
- data/lib/carrierwave_ext/micelaneous.rb +26 -0
- data/lib/carrierwave_ext/mongoid_embedded.rb +37 -0
- data/lib/carrierwave_ext/spec.rb +25 -0
- data/lib/carrierwave_ext.rb +17 -0
- data/lib/mongo_ext/spec.rb +11 -0
- data/lib/mongo_ext/upsert.rb +12 -0
- data/lib/mongo_ext.rb +3 -0
- data/lib/mongo_migration/adapters/mongoid.rb +9 -0
- data/lib/mongo_migration/definition.rb +19 -0
- data/lib/mongo_migration/migration.rb +71 -0
- data/lib/mongo_migration/tasks.rb +19 -0
- data/lib/mongo_migration.rb +14 -0
- data/lib/mongoid_misc/attribute_cache.rb +16 -0
- data/lib/mongoid_misc/attribute_convertors.rb +71 -0
- data/lib/mongoid_misc/belongs_to_with_counter_cache.rb +43 -0
- data/lib/mongoid_misc/gems.rb +16 -0
- data/lib/mongoid_misc/hacks.rb +43 -0
- data/lib/mongoid_misc/micelaneous.rb +91 -0
- data/lib/mongoid_misc/simple_finders.rb +44 -0
- data/lib/mongoid_misc/spec.rb +37 -0
- data/lib/mongoid_misc/support.rb +13 -0
- data/lib/mongoid_misc.rb +38 -0
- data/readme.md +85 -0
- data/spec/carrierwave_ext/mount_uploader_spec/plane.jpg +0 -0
- data/spec/carrierwave_ext/mount_uploader_spec/plane2.jpg +0 -0
- data/spec/carrierwave_ext/mount_uploader_spec.rb +158 -0
- data/spec/carrierwave_ext/spec_helper.rb +7 -0
- data/spec/carrierwave_ext/uploader_spec/ship.jpg +0 -0
- data/spec/carrierwave_ext/uploader_spec//321/204/320/260/320/270/314/206/320/273 /321/201 /320/277/321/200/320/276/320/261/320/265/320/273/320/260/320/274/320/270.txt" +1 -0
- data/spec/carrierwave_ext/uploader_spec.rb +61 -0
- data/spec/mongo_ext/spec_helper.rb +4 -0
- data/spec/mongo_ext/upsert_spec.rb +20 -0
- data/spec/mongo_migration/basic_spec.rb +110 -0
- data/spec/mongo_migration/spec_helper.rb +5 -0
- data/spec/mongoid_misc/attribute_convertors_spec.rb +70 -0
- data/spec/mongoid_misc/belongs_to_with_counter_cache_spec.rb +41 -0
- data/spec/mongoid_misc/micelaneous_spec.rb +92 -0
- data/spec/mongoid_misc/simple_finders_spec.rb +56 -0
- data/spec/mongoid_misc/spec_helper.rb +4 -0
- metadata +208 -0
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
CarrierWave::SanitizedFile.class_eval do
|
2
|
+
def sanitize_regexp
|
3
|
+
/[^[:word:]\.\-\+\s_]/i
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
CarrierWave::Uploader::Cache.class_eval do
|
8
|
+
def original_filename=(filename)
|
9
|
+
raise CarrierWave::InvalidParameter, "invalid filename" unless filename =~ /\A[[:word:]\.\-\+\s_]+\z/i
|
10
|
+
@original_filename = filename
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#
|
2
|
+
# Changing filename format from <version>_<filename_with_extension> to <name>.<version>.<extension>
|
3
|
+
#
|
4
|
+
CarrierWave::Uploader::Versions.class_eval do
|
5
|
+
def full_filename(for_file)
|
6
|
+
name = super
|
7
|
+
if version_name
|
8
|
+
ext = File.extname name
|
9
|
+
base = File.basename name, ext
|
10
|
+
"#{base}.#{version_name}#{ext}"
|
11
|
+
else
|
12
|
+
name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def full_original_filename
|
17
|
+
name = super
|
18
|
+
if version_name
|
19
|
+
ext = File.extname name
|
20
|
+
base = File.basename name, ext
|
21
|
+
"#{base}.#{version_name}#{ext}"
|
22
|
+
else
|
23
|
+
name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# Because of Mongoid doesn't fires some events on embedded documents
|
3
|
+
# (it has 'smart' callback system and doesn't fires :save/:destroy if document don't really saved/destroyed)
|
4
|
+
# we need to do it manually.
|
5
|
+
#
|
6
|
+
|
7
|
+
Mongoid::Document.class_eval do
|
8
|
+
def each_embedded association_name, &b
|
9
|
+
Array(send(association_name)).each &b
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module CarrierWave::MongoidEmbedded
|
14
|
+
extend ActiveSupport::Concern
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def mount_embedded_uploader association_name, column
|
18
|
+
after_save do |doc|
|
19
|
+
doc.each_embedded(association_name) do |embedded|
|
20
|
+
embedded.send "store_#{column}!"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
before_save do |doc|
|
25
|
+
doc.each_embedded(association_name) do |embedded|
|
26
|
+
embedded.send "write_#{column}_identifier"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
after_destroy do |doc|
|
31
|
+
doc.each_embedded(association_name) do |embedded|
|
32
|
+
embedded.send "remove_#{column}!"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'mongoid_misc/spec'
|
2
|
+
|
3
|
+
module CarrierWaveExtSpecHelper
|
4
|
+
TEST_PATH, TEST_CACHE_PATH = '/tmp/spec_fs', '/tmp/spec_fs_cache'
|
5
|
+
|
6
|
+
def with_files
|
7
|
+
before do
|
8
|
+
CarrierWave.configure do |config|
|
9
|
+
config.storage = :file
|
10
|
+
config.enable_processing = false
|
11
|
+
|
12
|
+
config.cache_dir = TEST_CACHE_PATH
|
13
|
+
config.root = TEST_PATH
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
[TEST_PATH, TEST_CACHE_PATH].each{|p| FileUtils.rm_r(p) if File.exist?(p)}
|
19
|
+
end
|
20
|
+
before do
|
21
|
+
[TEST_PATH, TEST_CACHE_PATH].each{|p| FileUtils.rm_r(p) if File.exist?(p)}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
rspec.extend CarrierWaveExtSpecHelper
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'carrierwave'
|
2
|
+
require 'carrierwave/validations/active_model'
|
3
|
+
require 'carrierwave/orm/mongoid'
|
4
|
+
|
5
|
+
%w(
|
6
|
+
fixes
|
7
|
+
micelaneous
|
8
|
+
mongoid_embedded
|
9
|
+
).each{|f| require "carrierwave_ext/#{f}"}
|
10
|
+
|
11
|
+
CarrierWave::Uploader::Base.class_eval do
|
12
|
+
def name; model.send("#{mounted_as}_filename") end
|
13
|
+
end
|
14
|
+
|
15
|
+
Mongoid::Document.class_eval do
|
16
|
+
include CarrierWave::MongoidEmbedded
|
17
|
+
end
|
data/lib/mongo_ext.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class Mongo::Migration::Definition
|
2
|
+
def upgrade &block
|
3
|
+
if block
|
4
|
+
@upgrade = block
|
5
|
+
else
|
6
|
+
@upgrade
|
7
|
+
end
|
8
|
+
end
|
9
|
+
alias_method :up, :upgrade
|
10
|
+
|
11
|
+
def downgrade &block
|
12
|
+
if block
|
13
|
+
@downgrade = block
|
14
|
+
else
|
15
|
+
@downgrade
|
16
|
+
end
|
17
|
+
end
|
18
|
+
alias_method :down, :downgrade
|
19
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Mongo::Migration
|
2
|
+
attr_accessor :adapter
|
3
|
+
|
4
|
+
def initialize adapter = nil
|
5
|
+
@adapter = adapter
|
6
|
+
end
|
7
|
+
|
8
|
+
def define version, database_name = :default, &block
|
9
|
+
raise "version should be an Integer! (but you provided '#{version}' instad)!" unless version.is_a? Integer
|
10
|
+
definition = Definition.new
|
11
|
+
block.call definition
|
12
|
+
definitions[database_name][version] = definition
|
13
|
+
end
|
14
|
+
|
15
|
+
def update version, database_name = :default
|
16
|
+
db = adapter.database database_name
|
17
|
+
|
18
|
+
if metadata(db)['version'] == version
|
19
|
+
adapter.logger.info "Database '#{database_name}' already is of #{version} version, no migration needed"
|
20
|
+
return false
|
21
|
+
else
|
22
|
+
adapter.logger.info "Migration for '#{database_name}', updating to #{version}"
|
23
|
+
end
|
24
|
+
|
25
|
+
increase_db_version database_name, db while metadata(db)['version'] < version
|
26
|
+
decrease_db_version database_name, db while metadata(db)['version'] > version
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def metadata db
|
31
|
+
col = db.collection 'db_metadata'
|
32
|
+
col.find_one || {'version' => 0}
|
33
|
+
end
|
34
|
+
|
35
|
+
def definitions
|
36
|
+
@definitions ||= Hash.new{|h, k| h[k] = []}
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def increase_db_version database_name, db
|
41
|
+
m = metadata(db)
|
42
|
+
migration = definitions[database_name][m['version'] + 1]
|
43
|
+
raise "No upgrade for version #{m['version'] + 1} of '#{database_name}' Database!" unless migration and migration.up
|
44
|
+
|
45
|
+
migration.up.call db
|
46
|
+
|
47
|
+
m['version'] += 1
|
48
|
+
update_metadata db, m
|
49
|
+
|
50
|
+
adapter.logger.info "Database '#{database_name}' upgraded to version #{m['version']}."
|
51
|
+
end
|
52
|
+
|
53
|
+
def decrease_db_version database_name, db
|
54
|
+
m = metadata(db)
|
55
|
+
migration = definitions[database_name][m['version']]
|
56
|
+
raise "No downgrade for version #{m['version']} of '#{database_name}' Database!" unless migration and migration.down
|
57
|
+
|
58
|
+
migration.down.call db
|
59
|
+
|
60
|
+
m['version'] -= 1
|
61
|
+
update_metadata db, m
|
62
|
+
|
63
|
+
adapter.logger.info "Database '#{database_name}' downgraded to version #{m['version']}."
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def update_metadata db, metadata
|
68
|
+
col = db.collection 'db_metadata'
|
69
|
+
col.save metadata.to_hash
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
namespace :db do
|
2
|
+
desc "Migrate Database"
|
3
|
+
task migrate: :migration_evnironment do
|
4
|
+
require 'mongo_migration'
|
5
|
+
|
6
|
+
database_name = (ENV['d'] || ENV['database'] || :default).to_sym
|
7
|
+
version = ENV['v'] || ENV['version']
|
8
|
+
|
9
|
+
if version.blank?
|
10
|
+
size = Mongo.migration.definitions[database_name].size
|
11
|
+
highest_defined_version = size == 0 ? 0 : size - 1
|
12
|
+
version = highest_defined_version
|
13
|
+
else
|
14
|
+
version = version.to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
Mongo.migration.update version, database_name
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Mongoid::AttributeConvertors
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
CONVERTORS = {
|
5
|
+
line: {
|
6
|
+
from_string: -> s {(s || "").split(',').collect{|s| s.strip}},
|
7
|
+
to_string: -> v {v.join(', ')}
|
8
|
+
},
|
9
|
+
column: {
|
10
|
+
from_string: -> s {(s || "").split("\n").collect{|s| s.strip}},
|
11
|
+
to_string: -> v {v.join("\n")}
|
12
|
+
},
|
13
|
+
yaml: {
|
14
|
+
from_string: -> s {YAML.load s rescue {}},
|
15
|
+
to_string: -> v {
|
16
|
+
# Mongoid uses it's internal Hash that doesn't support to_yaml
|
17
|
+
hash = {}; v.each{|k, v| hash[k] = v}
|
18
|
+
hash.to_yaml.strip
|
19
|
+
}
|
20
|
+
},
|
21
|
+
json: {
|
22
|
+
from_string: -> s {JSON.parse s rescue {}},
|
23
|
+
to_string: -> v {
|
24
|
+
# Mongoid uses it's internal Hash that doesn't support to_yaml
|
25
|
+
hash = {}; v.each{|k, v| hash[k] = v}
|
26
|
+
hash.to_json.strip
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
# supporf for :as_string option
|
33
|
+
def field name, options = {}
|
34
|
+
if converter_name = options[:as_string]
|
35
|
+
available_as_string name, converter_name
|
36
|
+
attr_protected "#{name}_as_string".to_sym if options[:protected]
|
37
|
+
end
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def available_as_string name, converter_name
|
43
|
+
converter = CONVERTORS[converter_name]
|
44
|
+
raise "unknown converter name :#{converter_name} for :#{name} field!" unless converter
|
45
|
+
|
46
|
+
from_string, to_string = converter[:from_string], converter[:to_string]
|
47
|
+
name_as_string = "#{name}_as_string".to_sym
|
48
|
+
define_method name_as_string do
|
49
|
+
cache[name_as_string] ||= to_string.call(send(name))
|
50
|
+
end
|
51
|
+
|
52
|
+
define_method "#{name_as_string}=" do |value|
|
53
|
+
cache.delete name_as_string
|
54
|
+
self.send "#{name}=", from_string.call(value)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def available_as_yaml name
|
59
|
+
raise "delimiter not specified for :#{name} field!" unless delimiter
|
60
|
+
method = "#{name}_as_string"
|
61
|
+
define_method method do
|
62
|
+
self.send(name).join(delimiter)
|
63
|
+
end
|
64
|
+
define_method "#{method}=" do |value|
|
65
|
+
value = (value || "").split(delimiter.strip).collect{|s| s.strip}
|
66
|
+
self.send "#{name}=", value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Mongoid::BelongsToWithCounterCache
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
#
|
6
|
+
# CounterCache
|
7
|
+
# belongs_to :item, counter_cashe: true
|
8
|
+
#
|
9
|
+
def belongs_to name, options = {}, &block
|
10
|
+
add_counter_cache name, options if options.delete(:counter_cache)
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
def add_counter_cache name, options
|
16
|
+
name = name.to_s
|
17
|
+
association_field = "#{name}_id"
|
18
|
+
cache_attribute_field = "#{self.alias.pluralize.underscore}_count"
|
19
|
+
cache_class = if class_name = options[:class_name]
|
20
|
+
class_name.constantize
|
21
|
+
else
|
22
|
+
name.classify.constantize
|
23
|
+
end
|
24
|
+
raise "field :#{cache_attribute_field} not defined on :#{cache_class}!" unless cache_class.fields.include? cache_attribute_field
|
25
|
+
increase_method_name = "increase_#{cache_class.alias.underscore}_#{self.alias.pluralize.underscore}_counter"
|
26
|
+
decrease_method_name = "decrease_#{cache_class.alias.underscore}_#{self.alias.pluralize.underscore}_counter"
|
27
|
+
|
28
|
+
define_method increase_method_name do
|
29
|
+
cache_class.upsert!({id: self.send(association_field)}, :$inc => {cache_attribute_field => 1})
|
30
|
+
end
|
31
|
+
protected increase_method_name
|
32
|
+
|
33
|
+
define_method decrease_method_name do
|
34
|
+
cache_class.upsert!({id: self.send(association_field)}, :$inc => {cache_attribute_field => -1})
|
35
|
+
end
|
36
|
+
protected decrease_method_name
|
37
|
+
|
38
|
+
after_create increase_method_name
|
39
|
+
after_destroy decrease_method_name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# dependencies for core gems
|
2
|
+
gem 'i18n', '0.5.0'
|
3
|
+
gem 'activesupport', '3.0.7'
|
4
|
+
gem 'activemodel', '3.0.7'
|
5
|
+
gem 'bson', '1.3.1'
|
6
|
+
gem 'bson_ext', '1.3.1'
|
7
|
+
gem 'mongo', '1.3.0'
|
8
|
+
gem 'will_paginate', '2.3.15'
|
9
|
+
|
10
|
+
gem 'mini_magick', '3.2.1'
|
11
|
+
gem 'subexec', '0.0.4'
|
12
|
+
|
13
|
+
# core gems
|
14
|
+
gem 'mongoid', '2.0.2'
|
15
|
+
|
16
|
+
gem 'carrierwave', '0.5.4'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Allow to specify different model name than class name
|
3
|
+
#
|
4
|
+
ActiveModel::Name.class_eval do
|
5
|
+
def initialize klass, name = nil
|
6
|
+
name ||= klass.name
|
7
|
+
|
8
|
+
super name
|
9
|
+
|
10
|
+
@klass = klass
|
11
|
+
@singular = ActiveSupport::Inflector.underscore(self).tr('/', '_').freeze
|
12
|
+
@plural = ActiveSupport::Inflector.pluralize(@singular).freeze
|
13
|
+
@element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze
|
14
|
+
@human = ActiveSupport::Inflector.humanize(@element).freeze
|
15
|
+
@collection = ActiveSupport::Inflector.tableize(self).freeze
|
16
|
+
@partial_path = "#{@collection}/#{@element}".freeze
|
17
|
+
@i18n_key = ActiveSupport::Inflector.underscore(self).tr('/', '.').to_sym
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
#
|
23
|
+
# Mongoid uses Proxy over Mongo::Collection, so we need to define all extra method on this proxy by hands
|
24
|
+
#
|
25
|
+
%w(upsert!).each do |name|
|
26
|
+
Mongoid::Collection.send(:define_method, name){|*args| master.collection.send(name, *args)}
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
#
|
31
|
+
# Default value on the :foreign_key
|
32
|
+
#
|
33
|
+
Mongoid::Relations::Metadata.class_eval do
|
34
|
+
def foreign_key_default_with_options
|
35
|
+
self[:default] || foreign_key_default_without_options
|
36
|
+
end
|
37
|
+
alias_method_chain :foreign_key_default, :options
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
#
|
42
|
+
# dynamic default scope
|
43
|
+
#
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Mongoid::Micelaneous
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
def upsert! *args
|
5
|
+
self.class.upsert!({id: id}, *args)
|
6
|
+
end
|
7
|
+
|
8
|
+
def exist?
|
9
|
+
self.class.where(_id: id).count > 0
|
10
|
+
end
|
11
|
+
alias_method :exists?, :exist?
|
12
|
+
|
13
|
+
def dom_id
|
14
|
+
new_record? ? "new_#{self.class.name.underscore}" : to_param
|
15
|
+
end
|
16
|
+
|
17
|
+
def first! *a
|
18
|
+
super || raise(Mongoid::Errors::DocumentNotFound.new(self, a))
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_protected_attributes attribute_names, attributes
|
22
|
+
attribute_names.each do |name|
|
23
|
+
send "#{name}=", attributes[name] if attributes.include? name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def t *a
|
28
|
+
I18n.t *a
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
# #
|
33
|
+
# # Database aliases
|
34
|
+
# #
|
35
|
+
# def set_database_alias als
|
36
|
+
# name = Mongoid.database_aliases[als] || raise("unknown database alias '#{als}'!")
|
37
|
+
# set_database name
|
38
|
+
# end
|
39
|
+
|
40
|
+
|
41
|
+
#
|
42
|
+
# model_name
|
43
|
+
#
|
44
|
+
def model_name *args
|
45
|
+
if args.empty?
|
46
|
+
@model_name ||= ::ActiveModel::Name.new self, self.alias
|
47
|
+
else
|
48
|
+
@model_name = ::ActiveModel::Name.new self, args.first
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
#
|
54
|
+
# Sequentiall :all for big collection
|
55
|
+
#
|
56
|
+
def all_sequentially &block
|
57
|
+
page, per_page = 1, 5
|
58
|
+
begin
|
59
|
+
results = paginate(page: page, per_page: per_page, order: '_id asc')
|
60
|
+
results.each{|o| block.call o}
|
61
|
+
page += 1
|
62
|
+
end until results.blank? or results.size < per_page
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
#
|
67
|
+
# shortcut for upsert
|
68
|
+
#
|
69
|
+
def upsert! query, *args
|
70
|
+
query[:_id] = query.delete :id if query.include? :id
|
71
|
+
collection.upsert! query, *args
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def to_param
|
76
|
+
(id || '').to_s
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# #
|
84
|
+
# # Database aliases
|
85
|
+
# #
|
86
|
+
# module Mongoid
|
87
|
+
# def self.database_aliases; @database_aliases ||= {} end
|
88
|
+
# def self.set_database_aliases aliases
|
89
|
+
# database_aliases.merge! aliases
|
90
|
+
# end
|
91
|
+
# end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Mongoid::SimpleFinders
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
def method_missing clause, *a, &b
|
6
|
+
if clause =~ /^([a-z]_by_[a-z_])|(by_[a-z_])/
|
7
|
+
clause = clause.to_s
|
8
|
+
|
9
|
+
bang = clause =~ /!$/
|
10
|
+
clause = clause[0..-2] if bang
|
11
|
+
|
12
|
+
finder, field = if clause =~ /^by_/
|
13
|
+
['first', clause.sub(/by_/, '')]
|
14
|
+
else
|
15
|
+
clause.split(/_by_/, 2)
|
16
|
+
end
|
17
|
+
finder = 'first' if finder == 'find'
|
18
|
+
|
19
|
+
raise "You can't use bang version with :#{finder}!" if bang and finder != 'first'
|
20
|
+
|
21
|
+
raise "invalid arguments for finder (#{a})!" unless a.size == 1
|
22
|
+
field_value = a.first
|
23
|
+
|
24
|
+
where(field => field_value).send(finder) ||
|
25
|
+
(bang && raise(Mongoid::Errors::DocumentNotFound.new(self, field_value)))
|
26
|
+
else
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# find_by_id, special case
|
33
|
+
#
|
34
|
+
def find_by_id id
|
35
|
+
where(_id: id).first
|
36
|
+
end
|
37
|
+
alias_method :by_id, :find_by_id
|
38
|
+
|
39
|
+
def find_by_id! id
|
40
|
+
find_by_id(id) || raise(Mongoid::Errors::DocumentNotFound.new(self, id))
|
41
|
+
end
|
42
|
+
alias_method :by_id!, :find_by_id!
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'mongo_ext/spec'
|
2
|
+
|
3
|
+
#
|
4
|
+
# disabling :set_database, all tests will use the same :test database.
|
5
|
+
#
|
6
|
+
Mongoid::MultiDatabase::ClassMethods.class_eval do
|
7
|
+
alias_method :_set_database, :set_database
|
8
|
+
def set_database database_name; end
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
# #
|
13
|
+
# # disabpling :set_database_alias
|
14
|
+
# #
|
15
|
+
# Mongoid::Micelaneous::ClassMethods.class_eval do
|
16
|
+
# alias_method :_set_database_alias, :set_database_alias
|
17
|
+
# def set_database_alias alias_name; end
|
18
|
+
# end
|
19
|
+
|
20
|
+
|
21
|
+
#
|
22
|
+
# Configuring Mongoid to use :test database and clearing database before each test
|
23
|
+
#
|
24
|
+
rspec do
|
25
|
+
def self.with_mongoid
|
26
|
+
before :all do
|
27
|
+
Mongoid.configure do |config|
|
28
|
+
connection = Mongo::Connection.new
|
29
|
+
config.master = connection.db('test')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
before do
|
34
|
+
clear_mongo_database
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|