mongoid_misc 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.
Files changed (42) hide show
  1. data/Rakefile +10 -0
  2. data/lib/carrierwave_ext/fixes.rb +12 -0
  3. data/lib/carrierwave_ext/micelaneous.rb +26 -0
  4. data/lib/carrierwave_ext/mongoid_embedded.rb +37 -0
  5. data/lib/carrierwave_ext/spec.rb +25 -0
  6. data/lib/carrierwave_ext.rb +17 -0
  7. data/lib/mongo_ext/spec.rb +11 -0
  8. data/lib/mongo_ext/upsert.rb +12 -0
  9. data/lib/mongo_ext.rb +3 -0
  10. data/lib/mongo_migration/adapters/mongoid.rb +9 -0
  11. data/lib/mongo_migration/definition.rb +19 -0
  12. data/lib/mongo_migration/migration.rb +71 -0
  13. data/lib/mongo_migration/tasks.rb +19 -0
  14. data/lib/mongo_migration.rb +14 -0
  15. data/lib/mongoid_misc/attribute_cache.rb +16 -0
  16. data/lib/mongoid_misc/attribute_convertors.rb +71 -0
  17. data/lib/mongoid_misc/belongs_to_with_counter_cache.rb +43 -0
  18. data/lib/mongoid_misc/gems.rb +16 -0
  19. data/lib/mongoid_misc/hacks.rb +43 -0
  20. data/lib/mongoid_misc/micelaneous.rb +91 -0
  21. data/lib/mongoid_misc/simple_finders.rb +44 -0
  22. data/lib/mongoid_misc/spec.rb +37 -0
  23. data/lib/mongoid_misc/support.rb +13 -0
  24. data/lib/mongoid_misc.rb +38 -0
  25. data/readme.md +85 -0
  26. data/spec/carrierwave_ext/mount_uploader_spec/plane.jpg +0 -0
  27. data/spec/carrierwave_ext/mount_uploader_spec/plane2.jpg +0 -0
  28. data/spec/carrierwave_ext/mount_uploader_spec.rb +158 -0
  29. data/spec/carrierwave_ext/spec_helper.rb +7 -0
  30. data/spec/carrierwave_ext/uploader_spec/ship.jpg +0 -0
  31. 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
  32. data/spec/carrierwave_ext/uploader_spec.rb +61 -0
  33. data/spec/mongo_ext/spec_helper.rb +4 -0
  34. data/spec/mongo_ext/upsert_spec.rb +20 -0
  35. data/spec/mongo_migration/basic_spec.rb +110 -0
  36. data/spec/mongo_migration/spec_helper.rb +5 -0
  37. data/spec/mongoid_misc/attribute_convertors_spec.rb +70 -0
  38. data/spec/mongoid_misc/belongs_to_with_counter_cache_spec.rb +41 -0
  39. data/spec/mongoid_misc/micelaneous_spec.rb +92 -0
  40. data/spec/mongoid_misc/simple_finders_spec.rb +56 -0
  41. data/spec/mongoid_misc/spec_helper.rb +4 -0
  42. metadata +208 -0
@@ -0,0 +1,38 @@
1
+ require 'mongoid_misc/gems'
2
+
3
+ require 'mongo_ext'
4
+ require 'mongoid'
5
+ require 'will_paginate'
6
+
7
+ %w(
8
+ hacks
9
+ support
10
+
11
+ attribute_cache
12
+ attribute_convertors
13
+ belongs_to_with_counter_cache
14
+ simple_finders
15
+ micelaneous
16
+ ).each{|file| require "mongoid_misc/#{file}"}
17
+
18
+ #
19
+ # Default plugins
20
+ #
21
+ [
22
+ Mongoid::AttributeCache,
23
+ Mongoid::AttributeConvertors,
24
+ Mongoid::BelongsToWithCounterCache,
25
+ Mongoid::SimpleFinders,
26
+ Mongoid::Micelaneous
27
+ ].each{|plugin| Mongoid::Document.send :include, plugin}
28
+
29
+
30
+ #
31
+ # Locales
32
+ #
33
+ # Mongoid.add_language "*" - can't use this there's some bug, haven't time to investigate it
34
+ Mongoid.add_language "en"
35
+ Mongoid.add_language "ru"
36
+
37
+ dir = File.expand_path "#{__FILE__}/../.."
38
+ I18n.load_path += Dir["#{dir}/config/locales/**/*.{rb,yml}"]
data/readme.md ADDED
@@ -0,0 +1,85 @@
1
+ ## Mongo Migrations
2
+
3
+ Migrations are framework-agnostic, You can use it with Mongoid, MongoMapper, or with just with bare Mongo driver.
4
+
5
+ require 'mongo_migration'
6
+ require 'mongo_migration/adapters/mongoid'
7
+
8
+ # use existing adapter or define Your own, it has only 2 methods
9
+ # and about 10 lines of code (use Mongoid as a sample)
10
+ adapter = Mongo::Migration::Mongoid.new
11
+
12
+ # initialize migration
13
+ Mongo.migration = Mongo::Migration.new adapter
14
+
15
+ # configure migration by defining migration steps
16
+ # You can place all of them in one file or as different
17
+ # files in one directory
18
+ Mongo.migration.define 1 do |m|
19
+ m.up do |db|
20
+ # update Your models
21
+ # User.create name: 'Bob'
22
+
23
+ # or use db directly
24
+ db.collection('users').insert({name: 'Bob'})
25
+ end
26
+ m.down{|db| db.collection('users').remove({name: 'Bob'})}
27
+ end
28
+
29
+ Mongo.migration.define 2 do |m|
30
+ m.up{|db| db.collection('users').insert({name: 'John'})}
31
+ m.down{|db| db.collection('users').remove({name: 'John'})}
32
+ end
33
+
34
+ # specify what version (it can be any version) do You need
35
+ # and apply migration
36
+ # You can call it directly or via Rake task
37
+ Mongo.migration.update 2
38
+ adapter.database(:default).collection('users').find.count.should == 2
39
+
40
+ # rollback to any version changes
41
+ Mongo.migration.update 0
42
+ adapter.database(:default).collection('users').find.count.should == 0
43
+
44
+ To see this code running go to spec.
45
+
46
+ # Mongoid
47
+
48
+ ## Attribute Converters
49
+
50
+ Handy shortcut to assign tags (Array) as a string with delimiters (there are also other converters for Lists, Hashes, Yaml):
51
+
52
+ class Post
53
+ include Mongoid::Document
54
+
55
+ field :tags, type: Array, default: [], as_string: :line
56
+ end
57
+
58
+ @post.tags_as_string = "personal, article"
59
+ @post.tags # => ['personal', 'article']
60
+ @post.tags_as_string # => "personal, article"
61
+
62
+ ## :counter_cache option
63
+
64
+ class Comment
65
+ belongs_to :post, counter_cache: true
66
+ end
67
+
68
+ Post.comments_count
69
+
70
+ ## Handy upserts
71
+
72
+ @post.upsert! :$inc => {comments_count: 1}
73
+
74
+ # Installation
75
+
76
+ gem install 'mongoid_misc'
77
+
78
+ require 'mongoid_misc'
79
+
80
+ # support for CarrierWave is optional
81
+ # require 'carrierwave_ext'
82
+
83
+ # License
84
+
85
+ Copyright (c) Alexey Petrushin [http://4ire.net](http://4ire.net), released under the MIT license.
@@ -0,0 +1,158 @@
1
+ require 'carrierwave_ext/spec_helper'
2
+
3
+ describe "Mongoid & CarrierWave" do
4
+ with_tmp_spec_dir
5
+ before :each do
6
+ connection = Mongo::Connection.new
7
+ connection.db('test').collection('test').drop
8
+
9
+ Mongoid.configure do |config|
10
+ config.master = connection.db('test')
11
+ end
12
+ end
13
+
14
+ before :all do
15
+ class PlaneImageUploader < CarrierWave::Uploader::Base
16
+ require 'carrierwave/processing/mini_magick'
17
+
18
+ include CarrierWave::MiniMagick
19
+
20
+ storage :file
21
+
22
+ version :icon do
23
+ process convert: :png
24
+ process resize_to_fit: [50, 50]
25
+ end
26
+
27
+ def store_dir
28
+ PlaneImageUploader.store_dir
29
+ end
30
+
31
+ def root
32
+ PlaneImageUploader.store_dir
33
+ end
34
+
35
+ class << self
36
+ attr_accessor :store_dir
37
+ end
38
+ end
39
+ end
40
+ after(:all){remove_constants :PlaneImageUploader}
41
+
42
+ before do
43
+ PlaneImageUploader.store_dir = "#{spec_dir}/data"
44
+ @file = File.new "#{spec_dir}/plane.jpg"
45
+ end
46
+ after do
47
+ @file.close
48
+ @file2.close if @file2
49
+ end
50
+
51
+ it "should works without model" do
52
+ # writing
53
+ uploader = PlaneImageUploader.new
54
+ uploader.store!(@file)
55
+ uploader.identifier.should == 'plane.jpg'
56
+ uploader.url.should == '/plane.jpg'
57
+ uploader.icon.url.should == '/plane.icon.jpg'
58
+ File.should exist("#{spec_dir}/data/plane.icon.jpg")
59
+
60
+ # reading
61
+ uploader = PlaneImageUploader.new
62
+ uploader.retrieve_from_store! 'plane.jpg'
63
+ uploader.url.should == '/plane.jpg'
64
+ uploader.icon.url.should == '/plane.icon.jpg'
65
+
66
+ # destroying
67
+ uploader = PlaneImageUploader.new
68
+ uploader.retrieve_from_store! 'plane.jpg'
69
+ uploader.remove!
70
+ File.should_not exist("#{spec_dir}/data/plane.icon.jpg")
71
+ end
72
+
73
+ describe "Document" do
74
+ before :all do
75
+ class Plane
76
+ include Mongoid::Document
77
+
78
+ mount_uploader :image, PlaneImageUploader
79
+ end
80
+ end
81
+ after(:all){remove_constants :Plane}
82
+
83
+ it "basic" do
84
+ Plane.create! image: @file
85
+ Plane.first.image.current_path.should =~ /\/plane.jpg/
86
+ File.should exist("#{spec_dir}/data/plane.jpg")
87
+ end
88
+
89
+ it "path format" do
90
+ Plane.create! image: @file
91
+
92
+ plane = Plane.first
93
+ plane.image.url.should == '/plane.jpg'
94
+ plane.image.icon.url.should =~ /\/plane\.icon\.jpg/
95
+ plane.image.name.should == 'plane.jpg'
96
+
97
+ plane.image.icon.current_path.should =~ /\/plane\.icon\.jpg/
98
+ File.should exist("#{spec_dir}/data/plane.icon.jpg")
99
+ end
100
+ end
101
+
102
+ describe "EmbeddedDocument" do
103
+ before :all do
104
+ class PlaneImage
105
+ include Mongoid::Document
106
+ embedded_in :plane, class_name: 'Plane2'
107
+ mount_uploader :image, PlaneImageUploader
108
+ end
109
+
110
+ class Plane2
111
+ include Mongoid::Document
112
+
113
+ embeds_many :images, class_name: 'PlaneImage'
114
+ mount_embedded_uploader :images, :image
115
+ end
116
+ end
117
+ after(:all){remove_constants :Plane2, :PlaneImage}
118
+
119
+ it "basic" do
120
+ Plane2.create! images: [PlaneImage.new(image: @file)]
121
+ Plane2.first.images.first.image.current_path.should =~ /\/plane.jpg/
122
+ File.should exist("#{spec_dir}/data/plane.jpg")
123
+ end
124
+
125
+ it "CRUD" do
126
+ # create
127
+ Plane2.create! images: [PlaneImage.new(image: @file)]
128
+ File.should exist("#{spec_dir}/data/plane.jpg")
129
+
130
+ # update
131
+ plane = Plane2.first
132
+ @file2 = File.new "#{spec_dir}/plane2.jpg"
133
+ plane.images << PlaneImage.new(image: @file2)
134
+ plane.save!
135
+ File.should exist("#{spec_dir}/data/plane2.jpg")
136
+
137
+ # destroy embedded
138
+ plane.images.last.destroy
139
+ File.should exist("#{spec_dir}/data/plane.jpg")
140
+ File.should_not exist("#{spec_dir}/data/plane2.jpg")
141
+
142
+ # destroy parent
143
+ plane.destroy
144
+ File.should_not exist("#{spec_dir}/data/plane.jpg")
145
+ end
146
+
147
+ it "path format" do
148
+ Plane2.create! images: [PlaneImage.new(image: @file)]
149
+
150
+ plane_image = Plane2.first.images.first
151
+ plane_image.image.url.should == '/plane.jpg'
152
+ plane_image.image.icon.url.should =~ /\/plane\.icon\.jpg/
153
+
154
+ plane_image.image.icon.current_path.should =~ /\/plane\.icon\.jpg/
155
+ File.should exist("#{spec_dir}/data/plane.icon.jpg")
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,7 @@
1
+ require "mongoid_misc"
2
+
3
+ require "carrierwave_ext"
4
+
5
+ require 'rspec_ext'
6
+ require 'mongoid_misc/spec'
7
+ require 'carrierwave_ext/spec'
@@ -0,0 +1,61 @@
1
+ require 'carrierwave_ext/spec_helper'
2
+ require 'carrierwave/processing/mini_magick'
3
+
4
+ describe "Uploading" do
5
+ with_tmp_spec_dir
6
+ with_mongoid
7
+ with_files
8
+
9
+ before :all do
10
+ class ImageUploader < CarrierWave::Uploader::Base
11
+ include CarrierWave::MiniMagick
12
+
13
+ # def sanitize_regexp
14
+ # /[^[:word:]\.\-\+\s_]/i
15
+ # end
16
+
17
+ def file_path
18
+ model.id
19
+ end
20
+
21
+ def store_dir
22
+ "#{root}#{file_path}"
23
+ end
24
+
25
+ def extension_white_list
26
+ [/.*/]
27
+ end
28
+ end
29
+
30
+ class Post
31
+ include Mongoid::Document
32
+
33
+ field :name, type: String, default: ""
34
+ validates_uniqueness_of :name
35
+
36
+ mount_uploader :image, ImageUploader
37
+ end
38
+ end
39
+ after(:all){remove_constants :Post, :ImageUploader}
40
+
41
+ it "should upload images" do
42
+ post = nil
43
+ File.open "#{spec_dir}/ship.jpg" do |f|
44
+ post = Post.new image: f
45
+ post.save!
46
+ end
47
+ post.image.url.should =~ /\/ship\.jpg/
48
+ post.image_filename.should =~ /ship\.jpg/
49
+ post.image.path.should =~ /\/ship\.jpg/
50
+ end
51
+
52
+ it "should preserve spaces and unicode characters in filename" do
53
+ File.open "#{spec_dir}/файл с пробелами.txt" do |f|
54
+ post = Post.new image: f
55
+
56
+ post.image.url.should =~ /\/файл с пробелами\.txt/
57
+ post.image.filename =~ /файл с пробелами\.txt/
58
+ post.image.path =~ /\/файл с пробелами\.txt/
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,4 @@
1
+ require 'mongo_ext'
2
+
3
+ require 'rspec_ext'
4
+ require 'mongo_ext/spec'
@@ -0,0 +1,20 @@
1
+ require 'mongo_ext/spec_helper'
2
+
3
+ describe "Micelaneous" do
4
+ before do
5
+ db = clear_mongo_database
6
+ @collection = db.collection 'test'
7
+ end
8
+
9
+ it "upsert should update" do
10
+ id = @collection.save count: 2
11
+ @collection.upsert!({_id: id}, :$inc => {count: 1})
12
+ @collection.find(_id: id).first['count'].should == 3
13
+ end
14
+
15
+ it "upsert should set" do
16
+ id = @collection.save({})
17
+ @collection.upsert!({_id: id}, :$inc => {count: 1})
18
+ @collection.find(_id: id).first['count'].should == 1
19
+ end
20
+ end
@@ -0,0 +1,110 @@
1
+ require 'mongo_migration/spec_helper'
2
+
3
+ describe "Migration" do
4
+ before :all do
5
+ class TestAdapter
6
+ def initialize
7
+ @logger = Logger.new(nil)
8
+
9
+ connection = Mongo::Connection.new
10
+ @databases = {
11
+ default: connection.db('test'),
12
+ global: connection.db('global_test')
13
+ }
14
+ end
15
+
16
+ attr_reader :logger
17
+ def database name; @databases[name] end
18
+ end
19
+ Mongo::Migration::Mongoid = TestAdapter
20
+ end
21
+ after(:all){remove_constants :TestAdapter, :MyAdapter}
22
+
23
+ before do
24
+ clear_mongo_database
25
+
26
+ @adapter = TestAdapter.new
27
+ @migration = Mongo::Migration.new @adapter
28
+ end
29
+
30
+ it "basic sample" do
31
+ # use existing adapter or define Your own, it has only 2 methods
32
+ # and about 10 lines of code (use Mongoid as a sample)
33
+ adapter = Mongo::Migration::Mongoid.new
34
+
35
+ # initialize migration
36
+ Mongo.migration = Mongo::Migration.new adapter
37
+
38
+ # configure migration by defining migration steps
39
+ # You can place all of them in one file or as different
40
+ # files in one directory
41
+ Mongo.migration.define 1 do |m|
42
+ m.up do |db|
43
+ # update Your models
44
+ # User.create name: 'Bob'
45
+
46
+ # or use db directly
47
+ db.collection('users').insert({name: 'Bob'})
48
+ end
49
+ m.down{|db| db.collection('users').remove({name: 'Bob'})}
50
+ end
51
+
52
+ Mongo.migration.define 2 do |m|
53
+ m.up{|db| db.collection('users').insert({name: 'John'})}
54
+ m.down{|db| db.collection('users').remove({name: 'John'})}
55
+ end
56
+
57
+ # specify what version (it can be any version) do You need
58
+ # and apply migration
59
+ # You can call it directly or via Rake task
60
+ Mongo.migration.update 2
61
+ adapter.database(:default).collection('users').find.count.should == 2
62
+
63
+ # rollback to any version changes
64
+ Mongo.migration.update 0
65
+ adapter.database(:default).collection('users').find.count.should == 0
66
+ end
67
+
68
+ it "Shouldn't update if versions are the same" do
69
+ @migration.update(0).should be_false
70
+ end
71
+
72
+ it "migration should provide access to database" do
73
+ @migration.define 1 do |m|
74
+ m.up do |db|
75
+ db.collection('users').insert({name: 'Bob'})
76
+ end
77
+ end
78
+ @migration.update(1).should be_true
79
+ @adapter.database(:default).collection('users').find.count.should == 1
80
+ end
81
+
82
+ it "increase_db_version" do
83
+ check = mock
84
+ @migration.define 1 do |m|
85
+ m.up{check.up}
86
+ end
87
+
88
+ check.should_receive :up
89
+ @migration.update(1).should be_true
90
+ @migration.metadata(@adapter.database(:default))['version'].should == 1
91
+ end
92
+
93
+ it "decrease_db_version" do
94
+ check = mock
95
+ @migration.define 1 do |m|
96
+ m.up{check.up}
97
+ m.down{check.down}
98
+ end
99
+ check.should_receive :up
100
+ @migration.update(1).should be_true
101
+
102
+ check.should_receive :down
103
+ @migration.update(0).should be_true
104
+ @migration.metadata(@adapter.database(:default))['version'].should == 0
105
+ end
106
+
107
+ describe "multiple databases" do
108
+ before{clear_mongo_database 'global_test'}
109
+ end
110
+ end
@@ -0,0 +1,5 @@
1
+ require 'logger'
2
+ require 'mongo_migration'
3
+
4
+ require 'rspec_ext'
5
+ require 'mongo_ext/spec'
@@ -0,0 +1,70 @@
1
+ require 'mongoid_misc/spec_helper'
2
+
3
+ describe "Attribute Convertors" do
4
+ with_mongoid
5
+
6
+ after(:all){remove_constants :TheSample}
7
+
8
+ before do
9
+ @convertors = Mongoid::AttributeConvertors::CONVERTORS
10
+ # @convertors.merge(test_convertor: {
11
+ # from_string: -> s {"from_string: #{s}"},
12
+ # to_string: -> v {"to_string: #{v}"}
13
+ # })
14
+ end
15
+
16
+ it ":line convertor" do
17
+ v = ['a', 'b']
18
+ str_v = 'a, b'
19
+ @convertors[:line][:from_string].call(str_v).should == v
20
+ @convertors[:line][:to_string].call(v).should == str_v
21
+ end
22
+
23
+ it ":yaml convertor" do
24
+ v = {'a' => 'b'}
25
+ str_v = v.to_yaml.strip
26
+
27
+ @convertors[:yaml][:from_string].call(str_v).should == v
28
+ @convertors[:yaml][:to_string].call(v).should == str_v
29
+ end
30
+
31
+ it ":json convertor" do
32
+ v = {'a' => 'b'}
33
+ str_v = v.to_json.strip
34
+ @convertors[:json][:from_string].call(str_v).should == v
35
+ @convertors[:json][:to_string].call(v).should == str_v
36
+ end
37
+
38
+ it ":field should generate helper methods if :as_string option provided" do
39
+ class ::TheSample
40
+ include Mongoid::Document
41
+
42
+ field :tags, type: Array, default: [], as_string: :line
43
+ field :protected_tags, type: Array, default: [], as_string: :line, protected: true
44
+ end
45
+
46
+ o = TheSample.new
47
+
48
+ # get
49
+ o.tags_as_string.should == ''
50
+ o.tags = %w(Java Ruby)
51
+ o.clear_cache
52
+ o.tags_as_string.should == 'Java, Ruby'
53
+
54
+ # set
55
+ o.tags_as_string = ''
56
+ o.tags.should == []
57
+ o.tags_as_string = 'Java, Ruby'
58
+ o.tags.should == %w(Java Ruby)
59
+
60
+ # mass assignment
61
+ o.tags = []
62
+ o.update_attributes tags_as_string: 'Java, Ruby'
63
+ o.tags.should == %w(Java Ruby)
64
+
65
+ # # protection
66
+ o.protected_tags = []
67
+ o.update_attributes protected_tags_as_string: 'Java, Ruby'
68
+ o.protected_tags.should == []
69
+ end
70
+ end
@@ -0,0 +1,41 @@
1
+ require 'mongoid_misc/spec_helper'
2
+
3
+ describe "BelongsToWithCounterCache" do
4
+ with_mongoid
5
+
6
+ before :all do
7
+ class ::Post
8
+ include Mongoid::Document
9
+
10
+ field :comments_count, type: Integer, default: 0
11
+ has_many :comments
12
+ end
13
+
14
+ class ::Comment
15
+ include Mongoid::Document
16
+
17
+ field :post_id
18
+ belongs_to :post, counter_cache: true
19
+ end
20
+ end
21
+ after(:all){remove_constants :Post, :Comment}
22
+
23
+ it "should increase count of comments" do
24
+ post = Post.create!
25
+ comment = post.comments.create!
26
+
27
+ post.reload
28
+ post.comments_count.should == 1
29
+ end
30
+
31
+ it "should decrease count of comments" do
32
+ post = Post.create!
33
+ comment = post.comments.create!
34
+ post.reload
35
+ post.comments_count.should == 1
36
+
37
+ comment.destroy
38
+ post.reload
39
+ post.comments_count.should == 0
40
+ end
41
+ end