shingara-mongomapper 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/.gitignore +7 -0
  2. data/History +70 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/Rakefile +73 -0
  6. data/VERSION +1 -0
  7. data/bin/mmconsole +56 -0
  8. data/lib/mongomapper.rb +77 -0
  9. data/lib/mongomapper/associations.rb +84 -0
  10. data/lib/mongomapper/associations/base.rb +69 -0
  11. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  12. data/lib/mongomapper/associations/belongs_to_proxy.rb +22 -0
  13. data/lib/mongomapper/associations/many_documents_proxy.rb +103 -0
  14. data/lib/mongomapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  15. data/lib/mongomapper/associations/many_embedded_proxy.rb +17 -0
  16. data/lib/mongomapper/associations/many_polymorphic_proxy.rb +11 -0
  17. data/lib/mongomapper/associations/many_proxy.rb +6 -0
  18. data/lib/mongomapper/associations/proxy.rb +63 -0
  19. data/lib/mongomapper/callbacks.rb +106 -0
  20. data/lib/mongomapper/document.rb +348 -0
  21. data/lib/mongomapper/dynamic_finder.rb +38 -0
  22. data/lib/mongomapper/embedded_document.rb +265 -0
  23. data/lib/mongomapper/finder_options.rb +85 -0
  24. data/lib/mongomapper/key.rb +76 -0
  25. data/lib/mongomapper/observing.rb +50 -0
  26. data/lib/mongomapper/pagination.rb +52 -0
  27. data/lib/mongomapper/rails_compatibility/document.rb +15 -0
  28. data/lib/mongomapper/rails_compatibility/embedded_document.rb +25 -0
  29. data/lib/mongomapper/save_with_validation.rb +19 -0
  30. data/lib/mongomapper/serialization.rb +55 -0
  31. data/lib/mongomapper/serializers/json_serializer.rb +92 -0
  32. data/lib/mongomapper/support.rb +30 -0
  33. data/lib/mongomapper/validations.rb +47 -0
  34. data/mongomapper.gemspec +142 -0
  35. data/test/NOTE_ON_TESTING +1 -0
  36. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +53 -0
  37. data/test/functional/associations/test_belongs_to_proxy.rb +45 -0
  38. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +131 -0
  39. data/test/functional/associations/test_many_embedded_proxy.rb +106 -0
  40. data/test/functional/associations/test_many_polymorphic_proxy.rb +261 -0
  41. data/test/functional/associations/test_many_proxy.rb +295 -0
  42. data/test/functional/test_associations.rb +47 -0
  43. data/test/functional/test_callbacks.rb +85 -0
  44. data/test/functional/test_document.rb +952 -0
  45. data/test/functional/test_pagination.rb +81 -0
  46. data/test/functional/test_rails_compatibility.rb +30 -0
  47. data/test/functional/test_validations.rb +172 -0
  48. data/test/models.rb +139 -0
  49. data/test/test_helper.rb +67 -0
  50. data/test/unit/serializers/test_json_serializer.rb +157 -0
  51. data/test/unit/test_association_base.rb +144 -0
  52. data/test/unit/test_document.rb +123 -0
  53. data/test/unit/test_embedded_document.rb +526 -0
  54. data/test/unit/test_finder_options.rb +183 -0
  55. data/test/unit/test_key.rb +247 -0
  56. data/test/unit/test_mongomapper.rb +28 -0
  57. data/test/unit/test_observing.rb +101 -0
  58. data/test/unit/test_pagination.rb +113 -0
  59. data/test/unit/test_rails_compatibility.rb +34 -0
  60. data/test/unit/test_serializations.rb +52 -0
  61. data/test/unit/test_validations.rb +259 -0
  62. metadata +189 -0
@@ -0,0 +1,7 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ *~
7
+ *.gem
data/History ADDED
@@ -0,0 +1,70 @@
1
+ 0.3.4 (master)
2
+ * BACKWORDS COMPATIBILITY BREAK: Timestamps are now optional. To use them add timestamps! to your model.
3
+ * BACKWORDS COMPATIBILITY BREAK: Associations keys are no longer created automatically when you use belongs_to and many. Too much was hidden from the developer. You now have to declare them like key :creator_id, String and such.
4
+
5
+ 0.3.3 8/16/2009
6
+ * BACKWORDS COMPATIBILITY BREAK: _id is now once again a string rather than an object id and will stay that way.
7
+ * Custom id's can now be used because of the change to string id's
8
+ * Added dynamic finders to document. (dcu)
9
+ * Added destroy_all, delete_all and nullify for many document association
10
+ * Added :dependent option for many documents assocation (dcu)
11
+ * update_attributes now returns true or false instead of the document. (Durran Jordan and me)
12
+ * Keys no longer require a type
13
+ * Keys can now be added on the fly using []=
14
+
15
+ 0.3.2 8/6/2009
16
+ * Added many polymorphic documents association
17
+ * Implemented build and create for many and many polymorphic documents
18
+ * <<, push and concat now work correctly for many and many polymorphic documents
19
+ * find(:first) now accepts order option
20
+ * id is now included by default with to_json
21
+ * _id is now always excluded from to_json
22
+ * Times are now always returned as UTC
23
+ * Default values are now a bit more intelligent for Array and Hash keys (djsun)
24
+ * Embedded documents now have _id as well so they can be identified more easily
25
+
26
+ 0.3.1 7/28/2009
27
+ * 1 minor tweak
28
+ * Removed deep_merge gem as dependency as ActiveSupport has deep_merge that works good enough
29
+
30
+ 0.3.0 7/28/2009
31
+ * 5 major additions, 3 minor additions, 3 bug fix, and other miscellany
32
+ * BACKWORDS COMPATIBILITY BREAK: _id is now stored in binary form (recommended by mongodb team) instead of string, api is the same everywhere as before but data stored with string id's previous to change will need to be updated
33
+ * Added Document#paginate which works just like find but adds pagination (dcu did basics and I pimped)
34
+ * Added a basic console for playing around with MongoMapper (dcu)
35
+ * Embedded associations can now be deeply nested (Keith Hanson)
36
+ * Added support for many polymorphic documents (Felipe Coury and Me)
37
+ * Fixed bug where conditions that disallowed using $in, $all and $any with an array
38
+ * Bumped version of validatable so :if validation option supports symbol/string to proc.
39
+ * Document#create with no attributes now creates a document as long as it is valid
40
+ * Now defining accessor methods when key is declared rather than using method missing and all that jazz
41
+ * Attributes now have boolean methods that return true or false based on whether they have value present
42
+ * Added scoped finds and pagination on many document association.
43
+ * find first and last now use natural order which is more reliable.
44
+ * Updated to latest ruby driver (0.10.1)
45
+
46
+
47
+ 0.2.0 7/7/2009
48
+ * 2 major additions (observers, associations), several minor additions, and a few bug fixes
49
+ * Added observers
50
+ * many now supports embedded docs or docs in another collection (dcu on github)
51
+ * added belongs_to association (dcu)
52
+ * added validates_uniqueness_of (dcu)
53
+ * added :unique key shortcut to add validates_uniqueness_of automatically
54
+ * now tracking descendants of document (dcu)
55
+ * added validates_exclusion_of and validates_inclusion_of
56
+ * Bumped required version of validatable for callback fixes
57
+ * More thorough use of converting find conditions and options to mongo speak
58
+ * #attributes= no longer bombs when given nil
59
+
60
+ 0.1.2 7/3/2009
61
+ * 2 minor changes
62
+ * Straightened out callbacks and added validate, validate_on_create and validate_on_update.
63
+ * Attributes passed into attributes= now call writer methods if they exist. This is mostly for virtual attributes.
64
+
65
+ 0.1.1 6/28/2009
66
+ * 1 minor change
67
+ * bumped ruby driver to 0.9 and removed hacks I had in while waiting for it
68
+
69
+ 0.1.0 6/26/2009
70
+ * Initial release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 John Nunemaker
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,39 @@
1
+ = MongoMapper
2
+
3
+ Awesome gem for modeling your domain and storing it in mongo.
4
+
5
+ Releases are tagged on github and also released as gems on github and rubyforge. Master is pushed to whenever I add a patch or a new feature. To build from master, you can clone the code, generate the updated gemspec, build the gem and install.
6
+
7
+ * rake gemspec
8
+ * gem build mongomapper.gemspec
9
+ * gem install the gem that was built
10
+
11
+ == Note on Patches/Pull Requests
12
+
13
+ * Fork the project.
14
+ * Make your feature addition or bug fix.
15
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
16
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself in another branch so I can ignore when I pull)
17
+ * Send me a pull request. Bonus points for topic branches.
18
+
19
+ == Dependencies
20
+
21
+ * ActiveSupport (activesupport)
22
+ * Mongo Ruby Driver (mongodb-mongo)
23
+ * My fork of the validatable gem (jnunemaker-validatable)
24
+
25
+ == Documentation
26
+
27
+ http://rdoc.info/projects/jnunemaker/mongomapper
28
+
29
+ == More Info
30
+
31
+ You can learn more about mongo here:
32
+ http://www.mongodb.org/
33
+
34
+ You can learn more about the mongo ruby driver here:
35
+ http://github.com/mongodb/mongo-ruby-driver/tree/master
36
+
37
+ == Copyright
38
+
39
+ Copyright (c) 2009 John Nunemaker. See LICENSE for details.
@@ -0,0 +1,73 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "mongomapper"
8
+ gem.summary = %Q{Awesome gem for modeling your domain and storing it in mongo}
9
+ gem.email = "nunemaker@gmail.com"
10
+ gem.homepage = "http://github.com/jnunemaker/mongomapper"
11
+ gem.authors = ["John Nunemaker"]
12
+ gem.rubyforge_project = "mongomapper"
13
+
14
+ gem.add_dependency('activesupport')
15
+ gem.add_dependency('mongodb-mongo', '0.11.1')
16
+ gem.add_dependency('jnunemaker-validatable', '1.7.2')
17
+
18
+ gem.add_development_dependency('mocha', '0.9.4')
19
+ gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
20
+ end
21
+
22
+ Jeweler::RubyforgeTasks.new do |rubyforge|
23
+ rubyforge.doc_task = "rdoc"
24
+ end
25
+ rescue LoadError
26
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
27
+ end
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ test.libs << 'lib' << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ begin
37
+ require 'rcov/rcovtask'
38
+ Rcov::RcovTask.new do |test|
39
+ test.libs << 'test'
40
+ test.pattern = 'test/**/test_*.rb'
41
+ test.verbose = true
42
+ end
43
+ rescue LoadError
44
+ task :rcov do
45
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
46
+ end
47
+ end
48
+
49
+ begin
50
+ require 'cucumber/rake/task'
51
+ Cucumber::Rake::Task.new(:features)
52
+ rescue LoadError
53
+ task :features do
54
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
55
+ end
56
+ end
57
+
58
+ task :default => :test
59
+
60
+ require 'rake/rdoctask'
61
+ Rake::RDocTask.new do |rdoc|
62
+ if File.exist?('VERSION.yml')
63
+ config = YAML.load(File.read('VERSION.yml'))
64
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
65
+ else
66
+ version = ""
67
+ end
68
+
69
+ rdoc.rdoc_dir = 'rdoc'
70
+ rdoc.title = "MongoMapper #{version}"
71
+ rdoc.rdoc_files.include('README*')
72
+ rdoc.rdoc_files.include('lib/**/*.rb')
73
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.3
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.dirname(__FILE__)+"/../lib"
3
+
4
+ require 'mongomapper'
5
+ require 'irb'
6
+
7
+ IRB.setup(nil)
8
+ irb = IRB::Irb.new
9
+
10
+ IRB.conf[:MAIN_CONTEXT] = irb.context
11
+
12
+ irb.context.evaluate("require 'irb/completion'", 0)
13
+ irb.context.evaluate(%@
14
+ include XGen::Mongo::Driver
15
+ include MongoMapper
16
+
17
+ MongoMapper.database = "mmtest"
18
+ $db = MongoMapper.database
19
+
20
+ @, 0)
21
+
22
+ puts %@
23
+ Welcome to the MongoMapper Console!
24
+
25
+ Example 1:
26
+ things = $db.collection("things")
27
+ things.insert("name" => "Raw Thing")
28
+ things.insert("name" => "Another Thing", "date" => Time.now)
29
+
30
+ cursor = things.find("name" => "Raw Thing")
31
+ puts cursor.next_object.inspect
32
+
33
+ Example 2:
34
+ class Thing
35
+ include MongoMapper::Document
36
+ key :name, String, :required => true
37
+ key :date, Time
38
+ end
39
+
40
+ thing = Thing.new
41
+ thing.name = "My thing"
42
+ thing.date = Time.now
43
+ thing.save
44
+
45
+ all_things = Thing.all
46
+ puts all_things.map { |object| object.name }.inspect
47
+
48
+ @
49
+
50
+ trap("SIGINT") do
51
+ irb.signal_handle
52
+ end
53
+ catch(:IRB_EXIT) do
54
+ irb.eval_input
55
+ end
56
+
@@ -0,0 +1,77 @@
1
+ require 'pathname'
2
+ require 'rubygems'
3
+
4
+ gem 'activesupport'
5
+ gem 'mongodb-mongo', '0.11.1'
6
+ gem 'jnunemaker-validatable', '1.7.2'
7
+
8
+ require 'activesupport'
9
+ require 'mongo'
10
+ require 'validatable'
11
+
12
+ dir = Pathname(__FILE__).dirname.expand_path + 'mongomapper'
13
+
14
+ require dir + 'support'
15
+
16
+ require dir + 'associations'
17
+ require dir + 'associations/base'
18
+
19
+ require dir + 'associations/proxy'
20
+ require dir + 'associations/many_documents_proxy'
21
+
22
+ require dir + 'associations/belongs_to_proxy'
23
+ require dir + 'associations/belongs_to_polymorphic_proxy'
24
+ require dir + 'associations/many_proxy'
25
+ require dir + 'associations/many_polymorphic_proxy'
26
+ require dir + 'associations/many_embedded_proxy'
27
+ require dir + 'associations/many_embedded_polymorphic_proxy'
28
+
29
+ require dir + 'callbacks'
30
+ require dir + 'finder_options'
31
+ require dir + 'dynamic_finder'
32
+ require dir + 'key'
33
+ require dir + 'observing'
34
+ require dir + 'pagination'
35
+ require dir + 'save_with_validation'
36
+ require dir + 'serialization'
37
+ require dir + 'validations'
38
+
39
+ require dir + 'rails_compatibility/document'
40
+ require dir + 'rails_compatibility/embedded_document'
41
+
42
+ require dir + 'embedded_document'
43
+ require dir + 'document'
44
+
45
+ module MongoMapper
46
+ DocumentNotFound = Class.new(StandardError)
47
+
48
+ DocumentNotValid = Class.new(StandardError) do
49
+ def initialize(document)
50
+ @document = document
51
+ super("Validation failed: #{@document.errors.full_messages.join(", ")}")
52
+ end
53
+ end
54
+
55
+ def self.connection
56
+ @@connection ||= XGen::Mongo::Driver::Mongo.new
57
+ end
58
+
59
+ def self.connection=(new_connection)
60
+ @@connection = new_connection
61
+ end
62
+
63
+ def self.database=(name)
64
+ @@databases ||= {}
65
+ unless @@databases.keys.include?(name.to_sym)
66
+ @@databases[name.to_sym] = MongoMapper.connection.db(name)
67
+ end
68
+ @@current_database = @@databases[name.to_sym]
69
+ end
70
+
71
+ def self.database(name=nil)
72
+ unless name.nil?
73
+ self.database = name
74
+ end
75
+ @@current_database
76
+ end
77
+ end
@@ -0,0 +1,84 @@
1
+ module MongoMapper
2
+ module Associations
3
+ module ClassMethods
4
+ def belongs_to(association_id, options = {})
5
+ create_association(:belongs_to, association_id, options)
6
+ self
7
+ end
8
+
9
+ def many(association_id, options = {})
10
+ create_association(:many, association_id, options)
11
+ self
12
+ end
13
+
14
+ def associations
15
+ @associations ||= HashWithIndifferentAccess.new
16
+ end
17
+
18
+ private
19
+ def create_association(type, name, options)
20
+ association = Associations::Base.new(type, name, options)
21
+ associations[association.name] = association
22
+ define_association_methods(association)
23
+ define_dependent_callback(association)
24
+ association
25
+ end
26
+
27
+ def define_association_methods(association)
28
+ define_method(association.name) do
29
+ get_proxy(association)
30
+ end
31
+
32
+ define_method("#{association.name}=") do |value|
33
+ get_proxy(association).replace(value)
34
+ value
35
+ end
36
+ end
37
+
38
+ def define_dependent_callback(association)
39
+ if association.options[:dependent]
40
+ if association.many?
41
+ define_dependent_callback_for_many(association)
42
+ elsif association.belongs_to?
43
+ define_dependent_callback_for_belongs_to(association)
44
+ end
45
+ end
46
+ end
47
+
48
+ def define_dependent_callback_for_many(association)
49
+ return if association.embeddable?
50
+
51
+ after_destroy do |doc|
52
+ case association.options[:dependent]
53
+ when :destroy
54
+ doc.get_proxy(association).destroy_all
55
+ when :delete_all
56
+ doc.get_proxy(association).delete_all
57
+ when :nullify
58
+ doc.get_proxy(association).nullify
59
+ end
60
+ end
61
+ end
62
+
63
+ def define_dependent_callback_for_belongs_to(association)
64
+ after_destroy do |doc|
65
+ case association.options[:dependent]
66
+ when :destroy
67
+ doc.get_proxy(association).destroy
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ module InstanceMethods
74
+ def get_proxy(association)
75
+ unless proxy = self.instance_variable_get(association.ivar)
76
+ proxy = association.proxy_class.new(self, association)
77
+ self.instance_variable_set(association.ivar, proxy) if !frozen?
78
+ end
79
+
80
+ proxy
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,69 @@
1
+ module MongoMapper
2
+ module Associations
3
+ class Base
4
+ attr_reader :type, :name, :options
5
+
6
+ def initialize(type, name, options = {})
7
+ @type, @name, @options = type, name, options
8
+ end
9
+
10
+ def class_name
11
+ @class_name ||= begin
12
+ if cn = options[:class_name]
13
+ cn
14
+ elsif many?
15
+ name.to_s.singularize.camelize
16
+ else
17
+ name.to_s.camelize
18
+ end
19
+ end
20
+ end
21
+
22
+ def klass
23
+ @klass ||= class_name.constantize
24
+ end
25
+
26
+ def many?
27
+ @many_type ||= @type == :many
28
+ end
29
+
30
+ def belongs_to?
31
+ @belongs_to_type ||= @type == :belongs_to
32
+ end
33
+
34
+ def polymorphic?
35
+ !!@options[:polymorphic]
36
+ end
37
+
38
+ def type_key_name
39
+ @type_key_name ||= many? ? '_type' : "#{name}_type"
40
+ end
41
+
42
+ def foreign_key
43
+ @options[:foreign_key] || "#{name}_id"
44
+ end
45
+
46
+ def ivar
47
+ @ivar ||= "@_#{name}"
48
+ end
49
+
50
+ def embeddable?
51
+ many? && klass.embeddable?
52
+ end
53
+
54
+ def proxy_class
55
+ @proxy_class ||= begin
56
+ if many?
57
+ if self.klass.embeddable?
58
+ polymorphic? ? ManyEmbeddedPolymorphicProxy : ManyEmbeddedProxy
59
+ else
60
+ polymorphic? ? ManyPolymorphicProxy : ManyProxy
61
+ end
62
+ else
63
+ polymorphic? ? BelongsToPolymorphicProxy : BelongsToProxy
64
+ end
65
+ end # end begin
66
+ end # end proxy_class
67
+ end
68
+ end
69
+ end