mongomodel 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.md +34 -0
- data/Rakefile +47 -0
- data/bin/console +45 -0
- data/lib/mongomodel.rb +92 -0
- data/lib/mongomodel/attributes/mongo.rb +40 -0
- data/lib/mongomodel/attributes/store.rb +30 -0
- data/lib/mongomodel/attributes/typecasting.rb +51 -0
- data/lib/mongomodel/concerns/abstract_class.rb +17 -0
- data/lib/mongomodel/concerns/activemodel.rb +11 -0
- data/lib/mongomodel/concerns/associations.rb +103 -0
- data/lib/mongomodel/concerns/associations/base/association.rb +33 -0
- data/lib/mongomodel/concerns/associations/base/definition.rb +56 -0
- data/lib/mongomodel/concerns/associations/base/proxy.rb +58 -0
- data/lib/mongomodel/concerns/associations/belongs_to.rb +68 -0
- data/lib/mongomodel/concerns/associations/has_many_by_foreign_key.rb +159 -0
- data/lib/mongomodel/concerns/associations/has_many_by_ids.rb +175 -0
- data/lib/mongomodel/concerns/attribute_methods.rb +55 -0
- data/lib/mongomodel/concerns/attribute_methods/before_type_cast.rb +29 -0
- data/lib/mongomodel/concerns/attribute_methods/dirty.rb +35 -0
- data/lib/mongomodel/concerns/attribute_methods/protected.rb +127 -0
- data/lib/mongomodel/concerns/attribute_methods/query.rb +22 -0
- data/lib/mongomodel/concerns/attribute_methods/read.rb +29 -0
- data/lib/mongomodel/concerns/attribute_methods/write.rb +29 -0
- data/lib/mongomodel/concerns/attributes.rb +85 -0
- data/lib/mongomodel/concerns/callbacks.rb +294 -0
- data/lib/mongomodel/concerns/logging.rb +15 -0
- data/lib/mongomodel/concerns/pretty_inspect.rb +29 -0
- data/lib/mongomodel/concerns/properties.rb +69 -0
- data/lib/mongomodel/concerns/record_status.rb +42 -0
- data/lib/mongomodel/concerns/timestamps.rb +32 -0
- data/lib/mongomodel/concerns/validations.rb +38 -0
- data/lib/mongomodel/concerns/validations/associated.rb +46 -0
- data/lib/mongomodel/document.rb +20 -0
- data/lib/mongomodel/document/callbacks.rb +46 -0
- data/lib/mongomodel/document/dynamic_finders.rb +88 -0
- data/lib/mongomodel/document/finders.rb +82 -0
- data/lib/mongomodel/document/indexes.rb +91 -0
- data/lib/mongomodel/document/optimistic_locking.rb +48 -0
- data/lib/mongomodel/document/persistence.rb +143 -0
- data/lib/mongomodel/document/scopes.rb +161 -0
- data/lib/mongomodel/document/validations.rb +68 -0
- data/lib/mongomodel/document/validations/uniqueness.rb +78 -0
- data/lib/mongomodel/embedded_document.rb +42 -0
- data/lib/mongomodel/locale/en.yml +55 -0
- data/lib/mongomodel/support/collection.rb +109 -0
- data/lib/mongomodel/support/configuration.rb +35 -0
- data/lib/mongomodel/support/core_extensions.rb +10 -0
- data/lib/mongomodel/support/exceptions.rb +25 -0
- data/lib/mongomodel/support/mongo_options.rb +177 -0
- data/lib/mongomodel/support/types.rb +35 -0
- data/lib/mongomodel/support/types/array.rb +11 -0
- data/lib/mongomodel/support/types/boolean.rb +25 -0
- data/lib/mongomodel/support/types/custom.rb +38 -0
- data/lib/mongomodel/support/types/date.rb +20 -0
- data/lib/mongomodel/support/types/float.rb +13 -0
- data/lib/mongomodel/support/types/hash.rb +18 -0
- data/lib/mongomodel/support/types/integer.rb +13 -0
- data/lib/mongomodel/support/types/object.rb +21 -0
- data/lib/mongomodel/support/types/string.rb +9 -0
- data/lib/mongomodel/support/types/symbol.rb +9 -0
- data/lib/mongomodel/support/types/time.rb +12 -0
- data/lib/mongomodel/version.rb +3 -0
- data/spec/mongomodel/attributes/store_spec.rb +273 -0
- data/spec/mongomodel/concerns/activemodel_spec.rb +61 -0
- data/spec/mongomodel/concerns/associations/belongs_to_spec.rb +153 -0
- data/spec/mongomodel/concerns/associations/has_many_by_foreign_key_spec.rb +165 -0
- data/spec/mongomodel/concerns/associations/has_many_by_ids_spec.rb +192 -0
- data/spec/mongomodel/concerns/attribute_methods/before_type_cast_spec.rb +46 -0
- data/spec/mongomodel/concerns/attribute_methods/dirty_spec.rb +131 -0
- data/spec/mongomodel/concerns/attribute_methods/protected_spec.rb +86 -0
- data/spec/mongomodel/concerns/attribute_methods/query_spec.rb +27 -0
- data/spec/mongomodel/concerns/attribute_methods/read_spec.rb +52 -0
- data/spec/mongomodel/concerns/attribute_methods/write_spec.rb +43 -0
- data/spec/mongomodel/concerns/attributes_spec.rb +152 -0
- data/spec/mongomodel/concerns/callbacks_spec.rb +90 -0
- data/spec/mongomodel/concerns/logging_spec.rb +20 -0
- data/spec/mongomodel/concerns/pretty_inspect_spec.rb +68 -0
- data/spec/mongomodel/concerns/properties_spec.rb +29 -0
- data/spec/mongomodel/concerns/timestamps_spec.rb +170 -0
- data/spec/mongomodel/concerns/validations_spec.rb +159 -0
- data/spec/mongomodel/document/callbacks_spec.rb +80 -0
- data/spec/mongomodel/document/dynamic_finders_spec.rb +183 -0
- data/spec/mongomodel/document/finders_spec.rb +231 -0
- data/spec/mongomodel/document/indexes_spec.rb +121 -0
- data/spec/mongomodel/document/optimistic_locking_spec.rb +57 -0
- data/spec/mongomodel/document/persistence_spec.rb +319 -0
- data/spec/mongomodel/document/scopes_spec.rb +204 -0
- data/spec/mongomodel/document/validations/uniqueness_spec.rb +217 -0
- data/spec/mongomodel/document/validations_spec.rb +132 -0
- data/spec/mongomodel/document_spec.rb +74 -0
- data/spec/mongomodel/embedded_document_spec.rb +66 -0
- data/spec/mongomodel/mongomodel_spec.rb +33 -0
- data/spec/mongomodel/support/collection_spec.rb +248 -0
- data/spec/mongomodel/support/mongo_options_spec.rb +295 -0
- data/spec/mongomodel/support/property_spec.rb +83 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/specdoc.opts +6 -0
- data/spec/support/callbacks.rb +44 -0
- data/spec/support/helpers/define_class.rb +24 -0
- data/spec/support/helpers/specs_for.rb +11 -0
- data/spec/support/matchers/be_a_subclass_of.rb +5 -0
- data/spec/support/matchers/respond_to_boolean.rb +17 -0
- data/spec/support/matchers/run_callbacks.rb +20 -0
- data/spec/support/models.rb +23 -0
- data/spec/support/time.rb +6 -0
- metadata +232 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2010 Sam Pohlenz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
MongoModel
|
2
|
+
==========
|
3
|
+
|
4
|
+
MongoModel is a Ruby ORM for interfacing with [MongoDB](http://www.mongodb.org/) databases.
|
5
|
+
|
6
|
+
|
7
|
+
Installation
|
8
|
+
============
|
9
|
+
|
10
|
+
MongoModel is distributed as a gem. Install with:
|
11
|
+
|
12
|
+
gem install mongomodel
|
13
|
+
|
14
|
+
|
15
|
+
Sample Usage
|
16
|
+
============
|
17
|
+
|
18
|
+
require 'mongomodel'
|
19
|
+
|
20
|
+
MongoModel.configuration = { 'host' => 'localhost', 'database' => 'mydb' }
|
21
|
+
|
22
|
+
class Article < MongoModel::Document
|
23
|
+
property :title, String, :default => 'Untitled'
|
24
|
+
property :body, String
|
25
|
+
property :published_at, Time, :protected => true
|
26
|
+
property :approved, Boolean, :default => false, :protected => true
|
27
|
+
|
28
|
+
timestamps!
|
29
|
+
|
30
|
+
validates_presence_of :title, :body
|
31
|
+
|
32
|
+
belongs_to :author, :class => User
|
33
|
+
end
|
34
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec/rake/spectask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
|
4
|
+
task :default => :spec
|
5
|
+
|
6
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
7
|
+
t.libs << 'lib'
|
8
|
+
t.spec_opts = ['--options', "#{File.expand_path(File.dirname(__FILE__))}/spec/spec.opts"]
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :spec do
|
12
|
+
desc "Run specs in nested documenting format"
|
13
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
14
|
+
t.libs << 'lib'
|
15
|
+
t.spec_opts = ['--options', "#{File.expand_path(File.dirname(__FILE__))}/spec/specdoc.opts"]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Generate documentation"
|
20
|
+
Rake::RDocTask.new(:doc) do |rdoc|
|
21
|
+
rdoc.rdoc_dir = 'doc'
|
22
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
23
|
+
rdoc.rdoc_files.include('lib')
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
require 'jeweler'
|
28
|
+
require File.dirname(__FILE__) + "/lib/mongomodel/version"
|
29
|
+
|
30
|
+
Jeweler::Tasks.new do |gem|
|
31
|
+
gem.name = "mongomodel"
|
32
|
+
gem.summary = "MongoDB ORM for Ruby/Rails"
|
33
|
+
gem.description = "MongoModel is a MongoDB ORM for Ruby/Rails similar to ActiveRecord, DataMapper."
|
34
|
+
gem.email = "sam@sampohlenz.com"
|
35
|
+
gem.homepage = "http://github.com/spohlenz/mongomodel"
|
36
|
+
gem.authors = ["Sam Pohlenz"]
|
37
|
+
gem.version = MongoModel::VERSION
|
38
|
+
|
39
|
+
gem.add_dependency('activesupport', '>= 3.0.pre')
|
40
|
+
gem.add_dependency('activemodel', '>= 3.0.pre')
|
41
|
+
gem.add_dependency('mongo', '>= 0.18.3')
|
42
|
+
end
|
43
|
+
|
44
|
+
Jeweler::GemcutterTasks.new
|
45
|
+
rescue LoadError
|
46
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
47
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
puts "Loading MongoModel sandbox..."
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
|
6
|
+
|
7
|
+
require 'irb'
|
8
|
+
require 'irb/completion'
|
9
|
+
|
10
|
+
require 'mongomodel'
|
11
|
+
|
12
|
+
IRB.setup(nil)
|
13
|
+
|
14
|
+
IRB.conf[:USE_READLINE] = true
|
15
|
+
IRB.conf[:PROMPT_MODE] = :SIMPLE
|
16
|
+
|
17
|
+
irb = IRB::Irb.new
|
18
|
+
|
19
|
+
IRB.conf[:MAIN_CONTEXT] = irb.context
|
20
|
+
|
21
|
+
examples = <<-EXAMPLES
|
22
|
+
|
23
|
+
class Article < MongoModel::Document
|
24
|
+
property :title, String
|
25
|
+
property :published, Boolean, :default => false
|
26
|
+
|
27
|
+
timestamps!
|
28
|
+
|
29
|
+
default_scope :order => :title.asc
|
30
|
+
|
31
|
+
named_scope :published, :conditions => { :published => true }
|
32
|
+
named_scope :latest, lambda { |num| { :limit => num, :order => 'created_at DESC' } }
|
33
|
+
end
|
34
|
+
|
35
|
+
EXAMPLES
|
36
|
+
|
37
|
+
puts examples
|
38
|
+
irb.context.evaluate(examples, 0)
|
39
|
+
|
40
|
+
trap("SIGINT") do
|
41
|
+
irb.signal_handle
|
42
|
+
end
|
43
|
+
catch(:IRB_EXIT) do
|
44
|
+
irb.eval_input
|
45
|
+
end
|
data/lib/mongomodel.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_model'
|
3
|
+
|
4
|
+
require 'mongo'
|
5
|
+
|
6
|
+
require 'mongomodel/support/core_extensions'
|
7
|
+
require 'mongomodel/support/exceptions'
|
8
|
+
require 'mongomodel/version'
|
9
|
+
|
10
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
11
|
+
|
12
|
+
module MongoModel
|
13
|
+
autoload :Document, 'mongomodel/document'
|
14
|
+
autoload :EmbeddedDocument, 'mongomodel/embedded_document'
|
15
|
+
|
16
|
+
autoload :Properties, 'mongomodel/concerns/properties'
|
17
|
+
autoload :Attributes, 'mongomodel/concerns/attributes'
|
18
|
+
autoload :AttributeMethods, 'mongomodel/concerns/attribute_methods'
|
19
|
+
autoload :Associations, 'mongomodel/concerns/associations'
|
20
|
+
autoload :Validations, 'mongomodel/concerns/validations'
|
21
|
+
autoload :Callbacks, 'mongomodel/concerns/callbacks'
|
22
|
+
autoload :Logging, 'mongomodel/concerns/logging'
|
23
|
+
autoload :Timestamps, 'mongomodel/concerns/timestamps'
|
24
|
+
autoload :PrettyInspect, 'mongomodel/concerns/pretty_inspect'
|
25
|
+
autoload :RecordStatus, 'mongomodel/concerns/record_status'
|
26
|
+
autoload :AbstractClass, 'mongomodel/concerns/abstract_class'
|
27
|
+
autoload :ActiveModelCompatibility, 'mongomodel/concerns/activemodel'
|
28
|
+
|
29
|
+
autoload :MongoOptions, 'mongomodel/support/mongo_options'
|
30
|
+
autoload :MongoOrder, 'mongomodel/support/mongo_options'
|
31
|
+
autoload :MongoOperator, 'mongomodel/support/mongo_options'
|
32
|
+
autoload :Types, 'mongomodel/support/types'
|
33
|
+
autoload :Configuration, 'mongomodel/support/configuration'
|
34
|
+
|
35
|
+
autoload :Collection, 'mongomodel/support/collection'
|
36
|
+
|
37
|
+
module AttributeMethods
|
38
|
+
autoload :Read, 'mongomodel/concerns/attribute_methods/read'
|
39
|
+
autoload :Write, 'mongomodel/concerns/attribute_methods/write'
|
40
|
+
autoload :Query, 'mongomodel/concerns/attribute_methods/query'
|
41
|
+
autoload :BeforeTypeCast, 'mongomodel/concerns/attribute_methods/before_type_cast'
|
42
|
+
autoload :Protected, 'mongomodel/concerns/attribute_methods/protected'
|
43
|
+
autoload :Dirty, 'mongomodel/concerns/attribute_methods/dirty'
|
44
|
+
end
|
45
|
+
|
46
|
+
module Attributes
|
47
|
+
autoload :Store, 'mongomodel/attributes/store'
|
48
|
+
autoload :Typecasting, 'mongomodel/attributes/typecasting'
|
49
|
+
autoload :Mongo, 'mongomodel/attributes/mongo'
|
50
|
+
end
|
51
|
+
|
52
|
+
module Associations
|
53
|
+
module Base
|
54
|
+
autoload :Definition, 'mongomodel/concerns/associations/base/definition'
|
55
|
+
autoload :Association, 'mongomodel/concerns/associations/base/association'
|
56
|
+
autoload :Proxy, 'mongomodel/concerns/associations/base/proxy'
|
57
|
+
end
|
58
|
+
|
59
|
+
autoload :BelongsTo, 'mongomodel/concerns/associations/belongs_to'
|
60
|
+
autoload :HasManyByIds, 'mongomodel/concerns/associations/has_many_by_ids'
|
61
|
+
autoload :HasManyByForeignKey, 'mongomodel/concerns/associations/has_many_by_foreign_key'
|
62
|
+
end
|
63
|
+
|
64
|
+
module DocumentExtensions
|
65
|
+
autoload :Persistence, 'mongomodel/document/persistence'
|
66
|
+
autoload :OptimisticLocking, 'mongomodel/document/optimistic_locking'
|
67
|
+
autoload :Finders, 'mongomodel/document/finders'
|
68
|
+
autoload :DynamicFinders, 'mongomodel/document/dynamic_finders'
|
69
|
+
autoload :Indexes, 'mongomodel/document/indexes'
|
70
|
+
autoload :Scopes, 'mongomodel/document/scopes'
|
71
|
+
autoload :Scope, 'mongomodel/document/scopes'
|
72
|
+
autoload :Validations, 'mongomodel/document/validations'
|
73
|
+
autoload :Callbacks, 'mongomodel/document/callbacks'
|
74
|
+
end
|
75
|
+
|
76
|
+
mattr_accessor :logger
|
77
|
+
|
78
|
+
def self.configuration
|
79
|
+
@_configuration ||= Configuration.defaults
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.configuration=(config)
|
83
|
+
@_database = nil
|
84
|
+
@_configuration = Configuration.new(config)
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.database
|
88
|
+
@_database ||= configuration.establish_connection
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
I18n.load_path << File.dirname(__FILE__) + '/mongomodel/locale/en.yml'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module MongoModel
|
2
|
+
module Attributes
|
3
|
+
module Mongo
|
4
|
+
def to_mongo
|
5
|
+
inject({}) do |result, (k, v)|
|
6
|
+
property = properties[k]
|
7
|
+
|
8
|
+
if property
|
9
|
+
result[property.as] = property.to_mongo(v)
|
10
|
+
else
|
11
|
+
converter = Types.converter_for(v.class)
|
12
|
+
result[k.to_s] = converter.to_mongo(v)
|
13
|
+
end
|
14
|
+
|
15
|
+
result
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def from_mongo!(hash)
|
20
|
+
hash.each do |k, v|
|
21
|
+
property = properties_as[k.to_s]
|
22
|
+
|
23
|
+
if property
|
24
|
+
self[property.name] = property.from_mongo(v)
|
25
|
+
else
|
26
|
+
self[k.to_sym] = v
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def properties_as
|
33
|
+
@properties_as ||= properties.inject({}) do |result, (name, property)|
|
34
|
+
result[property.as] = property
|
35
|
+
result
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
|
3
|
+
module MongoModel
|
4
|
+
module Attributes
|
5
|
+
class Store < ActiveSupport::OrderedHash
|
6
|
+
include Typecasting
|
7
|
+
include Mongo
|
8
|
+
|
9
|
+
attr_reader :instance
|
10
|
+
delegate :properties, :to => :instance
|
11
|
+
|
12
|
+
def initialize(instance)
|
13
|
+
super()
|
14
|
+
@instance = instance
|
15
|
+
set_defaults!
|
16
|
+
end
|
17
|
+
|
18
|
+
def inspect
|
19
|
+
"{#{map { |k, v| "#{k.inspect}=>#{v.inspect}"}.join(', ')}}"
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def set_defaults!
|
24
|
+
properties.each do |name, property|
|
25
|
+
self[name] = property.default(instance)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module MongoModel
|
2
|
+
module Attributes
|
3
|
+
module Typecasting
|
4
|
+
def []=(key, value)
|
5
|
+
values_before_typecast[key] = value
|
6
|
+
super(key, typecast(key, value))
|
7
|
+
end
|
8
|
+
|
9
|
+
# Check if key has a value that typecasts to true.
|
10
|
+
#
|
11
|
+
# attributes = Attributes::Store.new(:comments_count => Property.new(:comments_count, Integer))
|
12
|
+
#
|
13
|
+
# attributes[:comments_count] = 0
|
14
|
+
# attributes.has?(:comments_count)
|
15
|
+
# => false
|
16
|
+
#
|
17
|
+
# attributes[:comments_count] = 1
|
18
|
+
# attributes.has?(:comments_count)
|
19
|
+
# => true
|
20
|
+
#
|
21
|
+
def has?(key)
|
22
|
+
value = self[key]
|
23
|
+
boolean_typecast(key, value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def before_type_cast(key)
|
27
|
+
values_before_typecast[key]
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def typecast(key, value)
|
32
|
+
unless value.nil?
|
33
|
+
property = properties[key]
|
34
|
+
property ? property.cast(value) : value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def boolean_typecast(key, value)
|
39
|
+
if property = properties[key]
|
40
|
+
value ? property.boolean(value) : false
|
41
|
+
else
|
42
|
+
!!value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def values_before_typecast
|
47
|
+
@values_before_typecast ||= {}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module MongoModel
|
2
|
+
module AbstractClass
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def inherited(subclass)
|
6
|
+
subclass.abstract_class = false
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
attr_accessor :abstract_class
|
11
|
+
|
12
|
+
def abstract_class?
|
13
|
+
abstract_class == true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module MongoModel
|
2
|
+
module Associations
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def associations
|
6
|
+
@_associations ||= self.class.associations.inject({}) do |result, (name, association)|
|
7
|
+
result[name] = association.for(self)
|
8
|
+
result
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def belongs_to(name, options={})
|
14
|
+
associations[name] = create_association(BelongsTo, name, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_many(name, options={})
|
18
|
+
associations[name] = create_association(has_many_type(options), name, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def associations
|
22
|
+
read_inheritable_attribute(:associations) || write_inheritable_attribute(:associations, {})
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def has_many_type(options)
|
27
|
+
case options[:by]
|
28
|
+
when :ids
|
29
|
+
HasManyByIds
|
30
|
+
when :foreign_key
|
31
|
+
HasManyByForeignKey
|
32
|
+
else
|
33
|
+
ancestors.include?(Document) ? HasManyByForeignKey : HasManyByIds
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_association(type, name, options={})
|
38
|
+
type.new(self, name, options).define!
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
#
|
47
|
+
# belongs_to :user
|
48
|
+
# => property :user_id
|
49
|
+
# belongs_to :author, :class_name => 'User'
|
50
|
+
# => property :author_id
|
51
|
+
# belongs_to :commentable, :polymorphic => true
|
52
|
+
# => property :commentable_id
|
53
|
+
# => property :commentable_type
|
54
|
+
#
|
55
|
+
|
56
|
+
#
|
57
|
+
# has_many :contributors, :class_name => 'User', :foreign_key => :publication_id
|
58
|
+
# has_many :comments, :as => :commentable
|
59
|
+
# has_many :roles
|
60
|
+
#
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
#
|
66
|
+
# Documents and EmbeddedDocuments can:
|
67
|
+
# - belong to any Document
|
68
|
+
# - have many Documents by ids
|
69
|
+
#
|
70
|
+
# Documents can also:
|
71
|
+
# - have many Documents by foreign key
|
72
|
+
#
|
73
|
+
|
74
|
+
# class Author < Document; end
|
75
|
+
#
|
76
|
+
# class Comment < Document
|
77
|
+
# # Creates properties :commentable_id and :commentable_type
|
78
|
+
# belongs_to :commentable, :polymorphic => true
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# class Page < EmbeddedDocument
|
82
|
+
# # Creates property :editor_id
|
83
|
+
# belongs_to :editor, :class => 'Author'
|
84
|
+
#
|
85
|
+
# # Creates property :related_article_ids
|
86
|
+
# has_many :related_articles, :class => 'Article'
|
87
|
+
#
|
88
|
+
# # Polymorphic association, uses commentable_id/commentable_type on Comment class
|
89
|
+
# has_many :comments, :as => :commentable
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# class Article < Document
|
93
|
+
# # Creates property :author_id
|
94
|
+
# belongs_to :author
|
95
|
+
#
|
96
|
+
# # Creates property :recommended_by_ids
|
97
|
+
# has_many :recommended_by, :by => :ids, :class => 'Author'
|
98
|
+
#
|
99
|
+
# # Creates property :parent_article_id
|
100
|
+
# belongs_to :parent_article, :class => 'Article'
|
101
|
+
# # Uses parent_article_id property on referenced class
|
102
|
+
# has_many :child_articles, :by => :foreign_key, :foreign_key => :parent_article_id, :class => 'Article'
|
103
|
+
# end
|