mongo_doc 0.3.1 → 0.3.2

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/README.textile CHANGED
@@ -1,9 +1,17 @@
1
1
  h1. MongoDoc
2
2
 
3
- Version: 0.2.4 2/23/10
3
+ Version: 0.3.2 2010/03/11
4
4
 
5
- 2010-02-23 API is *changing* significantly
6
- 2010-01-23 Tracking MongoDoc with @git@? *READ THIS NOTE*[1]
5
+ * 2010-03-10 Slides are out of date, use key instead of attr_accessor with MongoDoc::Document (implementation was way too hackish)
6
+ * 2010-02-23 API is *changing* significantly
7
+ * 2010-01-23 Tracking MongoDoc with @git@? *READ THIS NOTE*[1]
8
+
9
+ h2. Quick Start
10
+
11
+ * install MongoDB (at least 1.3.2)
12
+ * install the Ruby driver @gem install mongo@
13
+ * install MongoDoc @gem install mongo_doc@
14
+ * run an example from this directory @ruby -Ilib examples/simple_object.rb@
7
15
 
8
16
  h2. Introduction
9
17
 
data/TODO CHANGED
@@ -1,4 +1,4 @@
1
- As of 2010-02-23
1
+ As of 2010-03-06
2
2
 
3
3
  Associations
4
4
  ------------
@@ -8,13 +8,18 @@ Pull associations out of attributes and refactor
8
8
  Criteria
9
9
  --------
10
10
 
11
- Make critieria module, include into Document, CriteriaProxy, Association?
11
+ Make critieria module; include into CriteriaProxy, Association?
12
+ page, per_page, paginate shuould be wrapped or not?
13
+
14
+ Contexts
15
+ --------
16
+
17
+ Extract Mongo context as module, Document#collection => klass.collection Collection#collection => klass
12
18
 
13
19
  Documentation
14
20
  -------------
15
21
 
16
22
  How to get started with Rails
17
- Using mongohq
18
23
 
19
24
  Dynamic Attributes
20
25
  ------------------
@@ -29,3 +34,7 @@ Validations
29
34
 
30
35
  validates_hash_keys :has_hash_name, :in => [array of names]
31
36
 
37
+
38
+ Q
39
+ -
40
+ What is Criteria#ids
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.3.2
@@ -25,7 +25,12 @@ Contact.collection.drop
25
25
  contact = Contact.new(:name => 'Hashrocket', :interests => ['ruby', 'rails', 'agile'])
26
26
  contact.addresses << Address.new(:street => '320 1st Street North, #712', :city => 'Jacksonville Beach', :state => 'FL', :zip_code => '32250', :phone_number => '877 885 8846')
27
27
  contact.save
28
+
29
+ # Finders
30
+ Contact.find_all.each {|c| puts c.name}
31
+ puts contact.to_param
28
32
  puts Contact.find_one(contact.to_param).addresses.first.street
33
+ Contact.find(contact.to_param).each {|c| puts c.name}
29
34
 
30
35
  hashrocket = Contact.in_state('FL').find {|contact| contact.name == 'Hashrocket'}
31
36
 
@@ -33,3 +38,9 @@ hashrocket_address = hashrocket.addresses.first
33
38
  hashrocket_address.update_attributes(:street => '320 First Street North, #712')
34
39
 
35
40
  puts Contact.where(:name => 'Hashrocket').first.addresses.first.street
41
+
42
+ # Criteria behave like new AR3 AREL queries
43
+ hr = Contact.where(:name => 'Hashrocket')
44
+ hr_in = hr.where('addresses.state' => 'IN')
45
+ puts hr.count
46
+ puts hr_in.count
@@ -25,6 +25,10 @@ contact.addresses = [address]
25
25
 
26
26
  collection.save(contact)
27
27
 
28
- results = collection.find('addresses.state' => 'FL')
29
- hashrocket = results.to_a.find {|contact| contact.name == 'Hashrocket'}
30
- puts hashrocket.addresses.first.phone_number
28
+ in_florida = collection.where('addresses.state' => 'FL')
29
+ puts in_florida.first.addresses.first.phone_number
30
+ rocket_oid_names = collection.where('name' => /rocket/)
31
+ puts rocket_oid_names.first.addresses.first.phone_number
32
+ interested_in_ruby = collection.in('interests' => ['ruby'])
33
+ puts interested_in_ruby.first.addresses.first.phone_number
34
+
@@ -0,0 +1,9 @@
1
+ Feature: Collection with Criteria
2
+
3
+ Scenario: saving a ruby object
4
+ Given a new collection named 'test'
5
+ And an object 'movie'
6
+ When I save the object 'movie'
7
+ And I query the collection 'test' with the criteria where(:title => 'Gone with the Wind')
8
+ Then the query result has 1 documents
9
+
@@ -12,3 +12,6 @@ Then /the collection should have (\d+) documents?/ do |count|
12
12
  @collection.count.should == count.to_i
13
13
  end
14
14
 
15
+ When "I query the collection '$collection_name' with the criteria $criteria" do |collection_name, criteria|
16
+ @query = eval("@collection.#{criteria}")
17
+ end
@@ -28,3 +28,11 @@ class Contact
28
28
  scope :contract_work, any_in(:interests => ['contract work'])
29
29
  scope :in_state, lambda {|state| where('addresses.state' => state)}
30
30
  end
31
+
32
+ class Event
33
+ include MongoDoc::Document
34
+
35
+ key :name
36
+ key :venue
37
+ key :date, :type => Date
38
+ end
@@ -7,18 +7,18 @@ end
7
7
 
8
8
  class Movie
9
9
  include ValueEquals
10
-
10
+
11
11
  attr_accessor :title, :director, :writers
12
12
  end
13
13
 
14
14
  class Director
15
15
  include ValueEquals
16
-
16
+
17
17
  attr_accessor :name, :awards
18
18
  end
19
19
 
20
20
  class AcademyAward
21
21
  include ValueEquals
22
-
22
+
23
23
  attr_accessor :year, :category
24
24
  end
@@ -6,6 +6,10 @@ def query(klass_name = nil)
6
6
  @query ||= klass(klass_name).criteria
7
7
  end
8
8
 
9
+ When "I also want a $number query with criteria $criteria" do |number, criteria|
10
+ instance_variable_set("@#{number}", eval("query.#{criteria}"))
11
+ end
12
+
9
13
  Then /^the query result is equal to the document '(.*)'$/ do |name|
10
14
  doc = instance_variable_get("@#{name}")
11
15
  query.should == doc
@@ -55,3 +59,8 @@ end
55
59
  Then /^the query (is|is not) (empty|blank)$/ do |is, empty|
56
60
  query.send("#{empty}?").should == (is == 'is')
57
61
  end
62
+
63
+ Then /^the (.+) query (is|is not) (empty|blank)$/ do |number, is, empty|
64
+ instance_variable_get("@#{number}").send("#{empty}?").should == (is == 'is')
65
+ end
66
+
@@ -0,0 +1,28 @@
1
+ def last
2
+ @last
3
+ end
4
+
5
+ def last=(value)
6
+ @last = value
7
+ end
8
+
9
+ def all
10
+ @all ||= []
11
+ end
12
+
13
+ def all=(value)
14
+ @all = value
15
+ end
16
+
17
+ Given /^a class Event$/ do
18
+ end
19
+
20
+ Given /^I create an (.+) '(.+)' with:$/ do |klass_name, object_name, table|
21
+ Given "an #{klass_name} document named '#{object_name}' :", table
22
+ end
23
+
24
+ Then /^the object '(.+)' has an attribute '(.+)' of type (.*)$/ do |object_name, attr_name, type_name|
25
+ object = instance_variable_get("@#{object_name}")
26
+ type_name.constantize.should === object.send(attr_name)
27
+ end
28
+
@@ -0,0 +1,10 @@
1
+ Feature: String casting
2
+
3
+ Background:
4
+ Given a class Event
5
+
6
+ Scenario: Creating a new document
7
+ When I create an Event 'event' with:
8
+ | Name | Venue | Date |
9
+ | NoSQL Live | John Hancock Conference Center | 2010-03-11 |
10
+ Then the object 'event' has an attribute 'date' of type Date
@@ -134,3 +134,9 @@ Feature: MongoDoc::Base
134
134
  Scenario: Is a criteria empty?
135
135
  When I query contacts with criteria all('interests' => ['ruby'])
136
136
  Then the query is not empty
137
+
138
+ Scenario: Criteria return a new criteria
139
+ When I query contacts with criteria all('interests' => ['ruby'])
140
+ And I also want a second query with criteria where('addresses.state' => 'HI')
141
+ Then the query is not empty
142
+ And the second query is empty
@@ -19,6 +19,20 @@ module MongoDoc
19
19
  end
20
20
  end
21
21
 
22
+ def attributes
23
+ hash = {}
24
+ self.class._attributes.each do |attr|
25
+ hash[attr] = send(attr)
26
+ end
27
+ hash
28
+ end
29
+
30
+ def attributes=(attrs)
31
+ attrs.each do |key, value|
32
+ send("#{key}=", value)
33
+ end
34
+ end
35
+
22
36
  def _root
23
37
  @_root
24
38
  end
@@ -42,9 +56,41 @@ module MongoDoc
42
56
  end
43
57
 
44
58
  def key(*args)
59
+ opts = args.extract_options!
60
+ default = opts.delete(:default)
61
+ type = opts.delete(:type)
45
62
  args.each do |name|
46
63
  _keys << name unless _keys.include?(name)
47
- attr_accessor name
64
+ if default
65
+ attr_writer name
66
+
67
+ define_method("_default_#{name}", default.kind_of?(Proc) ? default : Proc.new { default })
68
+ private "_default_#{name}"
69
+
70
+ module_eval(<<-RUBY, __FILE__, __LINE__)
71
+ def #{name}
72
+ unless defined? @#{name}
73
+ @#{name} = _default_#{name}
74
+ end
75
+ class << self; attr_reader :#{name} end
76
+ @#{name}
77
+ end
78
+ RUBY
79
+ else
80
+ attr_accessor name
81
+ end
82
+
83
+ if type and type.respond_to?(:cast_from_string)
84
+ module_eval(<<-RUBY, __FILE__, __LINE__)
85
+ def #{name}_with_type=(value) # def birth_date_with_type=(value)
86
+ if value.kind_of?(String) # if value.kind_of?(String)
87
+ value = #{type}.cast_from_string(value) # value = Date.cast_from_string(value)
88
+ end # end
89
+ self.#{name}_without_type = value # self.birth_date_without_type = value
90
+ end # end
91
+ RUBY
92
+ alias_method_chain "#{name}=", :type
93
+ end
48
94
  end
49
95
  end
50
96
 
@@ -1,18 +1,4 @@
1
- require 'mongo_doc/ext/array'
2
- require 'mongo_doc/ext/binary'
3
- require 'mongo_doc/ext/boolean_class'
4
- require 'mongo_doc/ext/date'
5
- require 'mongo_doc/ext/date_time'
6
- require 'mongo_doc/ext/dbref'
7
- require 'mongo_doc/ext/hash'
8
- require 'mongo_doc/ext/nil_class'
9
- require 'mongo_doc/ext/numeric'
10
- require 'mongo_doc/ext/object'
11
- require 'mongo_doc/ext/object_id'
12
- require 'mongo_doc/ext/regexp'
13
- require 'mongo_doc/ext/string'
14
- require 'mongo_doc/ext/symbol'
15
- require 'mongo_doc/ext/time'
1
+ require 'mongo_doc/ext'
16
2
 
17
3
  module MongoDoc
18
4
  module BSON
@@ -29,7 +15,7 @@ module MongoDoc
29
15
  bson
30
16
  end
31
17
  end
32
-
18
+
33
19
  def self.bson_create(bson_hash, options = {})
34
20
  return bson_hash if options[:raw_json]
35
21
  klass = bson_hash.delete(CLASS_KEY)
@@ -1,10 +1,33 @@
1
1
  require 'mongo_doc/cursor'
2
+ require 'mongo_doc/criteria'
2
3
 
3
4
  module MongoDoc
4
5
  class Collection
5
6
  attr_accessor :_collection
6
7
 
7
- delegate :[], :clear, :count, :create_index, :db, :distinct, :drop, :drop_index, :drop_indexes, :group, :hint, :index_information, :map_reduce, :mapreduce, :name, :options, :pk_factory, :remove, :rename, :size, :to => :_collection
8
+ include MongoDoc::Criteria
9
+
10
+ delegate \
11
+ :[],
12
+ :clear,
13
+ :count,
14
+ :create_index,
15
+ :db,
16
+ :distinct,
17
+ :drop,
18
+ :drop_index,
19
+ :drop_indexes,
20
+ :group,
21
+ :hint,
22
+ :index_information,
23
+ :map_reduce,
24
+ :mapreduce,
25
+ :name,
26
+ :options,
27
+ :pk_factory,
28
+ :remove,
29
+ :rename,
30
+ :size, :to => :_collection
8
31
 
9
32
  def initialize(name)
10
33
  self._collection = self.class.mongo_collection(name)
@@ -40,6 +63,10 @@ module MongoDoc
40
63
 
41
64
  protected
42
65
 
66
+ def collection
67
+ self
68
+ end
69
+
43
70
  def last_error
44
71
  MongoDoc::Connection.database.command({'getlasterror' => 1})
45
72
  end
@@ -6,6 +6,9 @@ require "mongo_doc/contexts/mongo"
6
6
 
7
7
  module Mongoid
8
8
  module Contexts
9
+
10
+ class UnknownContext < RuntimeError; end
11
+
9
12
  # Determines the context to be used for this criteria. If the class is an
10
13
  # embedded document, then the context will be the array in the has_many
11
14
  # association it is in. If the class is a root, then the database itself
@@ -15,10 +18,13 @@ module Mongoid
15
18
  #
16
19
  # <tt>Contexts.context_for(criteria)</tt>
17
20
  def self.context_for(criteria)
18
- if criteria.klass.respond_to?(:collection)
21
+ if criteria.klass.respond_to?(:_append)
22
+ return MongoDoc::Contexts::Enumerable.new(criteria)
23
+ elsif criteria.klass.respond_to?(:collection)
19
24
  return MongoDoc::Contexts::Mongo.new(criteria)
25
+ else
26
+ raise UnknownContext.new("Context not found for: #{criteria.klass}")
20
27
  end
21
- return MongoDoc::Contexts::Enumerable.new(criteria)
22
28
  end
23
29
 
24
30
  end
@@ -10,27 +10,59 @@ module MongoDoc
10
10
  #
11
11
  # <tt>Person.criteria</tt>
12
12
  def criteria
13
- Mongoid::Criteria.new(self)
13
+ CriteriaWrapper.new(self)
14
14
  end
15
15
 
16
16
  delegate \
17
+ :aggregate,
18
+ :all,
17
19
  :and,
18
20
  :any_in,
19
- :cache,
20
- :enslave,
21
+ :blank?,
22
+ :count,
23
+ :empty?,
21
24
  :excludes,
22
25
  :extras,
26
+ :first,
27
+ :group,
23
28
  :id,
24
29
  :in,
30
+ :last,
25
31
  :limit,
32
+ :max,
33
+ :min,
26
34
  :not_in,
27
35
  :offset,
36
+ :one,
28
37
  :only,
29
38
  :order_by,
30
39
  :page,
40
+ :paginate,
31
41
  :per_page,
32
42
  :skip,
43
+ :sum,
33
44
  :where, :to => :criteria
45
+
46
+ class CriteriaWrapper < Mongoid::Criteria
47
+ %w(all and any_in cache enslave excludes extras fuse in limit not_in offset only order_by skip where).each do |method|
48
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
49
+ def #{method}_with_wrapping(*args, &block) # def and(*args, &block)
50
+ new_criteria = CriteriaWrapper.new(klass) # new_criteria = CriteriaWrapper.new(klass)
51
+ new_criteria.merge(self) # new_criteria.merge(criteria)
52
+ new_criteria.#{method}_without_wrapping(*args, &block) # new_criteria.and_without_wrapping(*args, &block)
53
+ new_criteria # new_criteria
54
+ end # end
55
+
56
+ alias_method_chain :#{method}, :wrapping
57
+ protected :#{method}_without_wrapping
58
+ RUBY
59
+ end
60
+
61
+ protected
62
+
63
+ attr_accessor :criteria
64
+
65
+ end
34
66
  end
35
67
  end
36
68
 
@@ -36,20 +36,6 @@ module MongoDoc
36
36
  self.class._attributes.all? {|var| self.send(var) == other.send(var)}
37
37
  end
38
38
 
39
- def attributes
40
- hash = {}
41
- self.class._attributes.each do |attr|
42
- hash[attr] = send(attr)
43
- end
44
- hash
45
- end
46
-
47
- def attributes=(attrs)
48
- attrs.each do |key, value|
49
- send("#{key}=", value)
50
- end
51
- end
52
-
53
39
  def new_record?
54
40
  _id.nil?
55
41
  end
@@ -132,13 +118,13 @@ module MongoDoc
132
118
 
133
119
  def create(attrs = {})
134
120
  instance = new(attrs)
135
- instance.save(false)
121
+ instance.save(true)
136
122
  instance
137
123
  end
138
124
 
139
125
  def create!(attrs = {})
140
126
  instance = new(attrs)
141
- instance.save!(true)
127
+ instance.save!
142
128
  instance
143
129
  end
144
130
  end
@@ -1,3 +1,9 @@
1
+ class Boolean
2
+ def self.cast_from_string(value)
3
+ value == '1' || value.downcase == 'true'
4
+ end
5
+ end
6
+
1
7
  class FalseClass
2
8
  def to_bson(*args)
3
9
  self
@@ -8,4 +14,4 @@ class TrueClass
8
14
  def to_bson(*args)
9
15
  self
10
16
  end
11
- end
17
+ end
@@ -13,4 +13,7 @@ class Date
13
13
  Date.parse(*bson_hash.values_at('dt', 'sg'))
14
14
  end
15
15
 
16
+ def self.cast_from_string(value)
17
+ Date.parse(value) unless value.blank?
18
+ end
16
19
  end
@@ -10,4 +10,8 @@ class DateTime
10
10
  def self.bson_create(bson_hash, options = nil)
11
11
  DateTime.parse(*bson_hash.values_at('dt', 'sg'))
12
12
  end
13
+
14
+ def self.cast_from_string(string)
15
+ DateTime.parse(string) unless string.blank?
16
+ end
13
17
  end
@@ -4,14 +4,14 @@ class Numeric
4
4
  end
5
5
  end
6
6
 
7
- class Float
8
- def to_bson(*args)
9
- self
7
+ class BigDecimal
8
+ def self.cast_from_string(string)
9
+ BigDecimal.new(string) unless string.blank?
10
10
  end
11
11
  end
12
12
 
13
13
  class Integer
14
- def to_bson(*args)
15
- self
14
+ def self.cast_from_string(string)
15
+ string.to_i unless string.blank?
16
16
  end
17
17
  end
@@ -2,4 +2,8 @@ class Time
2
2
  def to_bson(*args)
3
3
  self
4
4
  end
5
- end
5
+
6
+ def self.cast_from_string(string)
7
+ Time.parse(string) unless string.blank?
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ require 'mongo_doc/ext/array'
2
+ require 'mongo_doc/ext/binary'
3
+ require 'mongo_doc/ext/boolean_class'
4
+ require 'mongo_doc/ext/date'
5
+ require 'mongo_doc/ext/date_time'
6
+ require 'mongo_doc/ext/dbref'
7
+ require 'mongo_doc/ext/hash'
8
+ require 'mongo_doc/ext/nil_class'
9
+ require 'mongo_doc/ext/numeric'
10
+ require 'mongo_doc/ext/object'
11
+ require 'mongo_doc/ext/object_id'
12
+ require 'mongo_doc/ext/regexp'
13
+ require 'mongo_doc/ext/string'
14
+ require 'mongo_doc/ext/symbol'
15
+ require 'mongo_doc/ext/time'
@@ -6,17 +6,6 @@ module MongoDoc
6
6
  base.extend(Criteria) unless base === Criteria
7
7
  end
8
8
 
9
- %w(count first last).each do |name|
10
- module_eval <<-RUBY
11
- # #{name.humanize} for this +Document+ class
12
- #
13
- # <tt>Person.#{name}</tt>
14
- def #{name}
15
- criteria.#{name}
16
- end
17
- RUBY
18
- end
19
-
20
9
  # Find a +Document+ based on id (+String+ or +Mongo::ObjectID+)
21
10
  #
22
11
  # <tt>Person.find('1')</tt>
@@ -22,6 +22,7 @@ module Mongoid #:nodoc:
22
22
  def all(attributes = {})
23
23
  update_selector(attributes, "$all")
24
24
  end
25
+ alias :all_in :all
25
26
 
26
27
  # Adds a criterion to the +Criteria+ that specifies values that must
27
28
  # be matched in order to return results. This is similar to a SQL "WHERE"
@@ -61,7 +62,7 @@ module Mongoid #:nodoc:
61
62
  def in(attributes = {})
62
63
  update_selector(attributes, "$in")
63
64
  end
64
- alias any_in in
65
+ alias :any_in :in
65
66
 
66
67
  # Adds a criterion to the +Criteria+ that specifies values that must
67
68
  # be matched in order to return results. This is similar to a SQL "WHERE"
data/mongo_doc.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongo_doc}
8
- s.version = "0.3.1"
8
+ s.version = "0.3.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Les Hill"]
12
- s.date = %q{2010-03-06}
12
+ s.date = %q{2010-03-11}
13
13
  s.description = %q{ODM for MongoDB}
14
14
  s.email = %q{leshill@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
28
28
  "data/.gitignore",
29
29
  "examples/simple_document.rb",
30
30
  "examples/simple_object.rb",
31
+ "features/collections.feature",
31
32
  "features/finders.feature",
32
33
  "features/mongodb.yml",
33
34
  "features/mongodoc_base.feature",
@@ -47,7 +48,9 @@ Gem::Specification.new do |s|
47
48
  "features/step_definitions/query_steps.rb",
48
49
  "features/step_definitions/removing_documents_steps.rb",
49
50
  "features/step_definitions/scope_steps.rb",
51
+ "features/step_definitions/string_casting_steps.rb",
50
52
  "features/step_definitions/util_steps.rb",
53
+ "features/string_casting.feature",
51
54
  "features/support/support.rb",
52
55
  "features/using_criteria.feature",
53
56
  "lib/mongo_doc.rb",
@@ -66,6 +69,7 @@ Gem::Specification.new do |s|
66
69
  "lib/mongo_doc/criteria.rb",
67
70
  "lib/mongo_doc/cursor.rb",
68
71
  "lib/mongo_doc/document.rb",
72
+ "lib/mongo_doc/ext.rb",
69
73
  "lib/mongo_doc/ext/array.rb",
70
74
  "lib/mongo_doc/ext/binary.rb",
71
75
  "lib/mongo_doc/ext/boolean_class.rb",
@@ -115,6 +119,7 @@ Gem::Specification.new do |s|
115
119
  "spec/associations/collection_proxy_spec.rb",
116
120
  "spec/associations/document_proxy_spec.rb",
117
121
  "spec/associations/hash_proxy_spec.rb",
122
+ "spec/attributes_accessor_spec.rb",
118
123
  "spec/attributes_spec.rb",
119
124
  "spec/bson_matchers.rb",
120
125
  "spec/bson_spec.rb",
@@ -129,6 +134,7 @@ Gem::Specification.new do |s|
129
134
  "spec/document_ext.rb",
130
135
  "spec/document_spec.rb",
131
136
  "spec/embedded_save_spec.rb",
137
+ "spec/ext_spec.rb",
132
138
  "spec/finders_spec.rb",
133
139
  "spec/hash_matchers.rb",
134
140
  "spec/matchers_spec.rb",
@@ -149,6 +155,7 @@ Gem::Specification.new do |s|
149
155
  "spec/associations/collection_proxy_spec.rb",
150
156
  "spec/associations/document_proxy_spec.rb",
151
157
  "spec/associations/hash_proxy_spec.rb",
158
+ "spec/attributes_accessor_spec.rb",
152
159
  "spec/attributes_spec.rb",
153
160
  "spec/bson_matchers.rb",
154
161
  "spec/bson_spec.rb",
@@ -163,6 +170,7 @@ Gem::Specification.new do |s|
163
170
  "spec/document_ext.rb",
164
171
  "spec/document_spec.rb",
165
172
  "spec/embedded_save_spec.rb",
173
+ "spec/ext_spec.rb",
166
174
  "spec/finders_spec.rb",
167
175
  "spec/hash_matchers.rb",
168
176
  "spec/matchers_spec.rb",
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe "MongoDoc::Attributes attributes accessor" do
4
+ class AttributesTest
5
+ include MongoDoc::Attributes
6
+
7
+ key :name
8
+ key :age
9
+ key :birthdate
10
+ end
11
+
12
+ context "#attributes" do
13
+ subject do
14
+ AttributesTest.new.attributes
15
+ end
16
+
17
+ it "returns a hash of the given attributes" do
18
+ should have_key(:name)
19
+ should have_key(:age)
20
+ should have_key(:birthdate)
21
+ end
22
+ end
23
+
24
+ context "#attributes=" do
25
+ let(:object) { AttributesTest.new }
26
+
27
+ it "sets attributes from a hash" do
28
+ name = 'name'
29
+ object.attributes = {:name => name}
30
+ object.name.should == name
31
+ end
32
+ end
33
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe "MongoDoc::Attributes" do
4
4
  class AttributesTest
@@ -12,22 +12,20 @@ describe "MongoDoc::Attributes" do
12
12
 
13
13
  context ".key" do
14
14
  class TestKeys
15
- include MongoDoc::Document
15
+ include MongoDoc::Attributes
16
+
17
+ key :attr1, :attr2
16
18
  end
17
19
 
18
20
  it "adds its arguments to _keys" do
19
- TestKeys.key :attr1, :attr2
20
21
  TestKeys._keys.should == [:attr1, :attr2]
21
22
  end
22
23
 
23
24
  describe "accessors" do
24
- before do
25
- TestKeys.key :attr1
26
- end
27
-
28
25
  subject do
29
26
  TestKeys.new
30
27
  end
28
+
31
29
  it "has an attr1 reader" do
32
30
  should respond_to(:attr1)
33
31
  end
@@ -37,9 +35,67 @@ describe "MongoDoc::Attributes" do
37
35
  end
38
36
  end
39
37
 
38
+ context "default values" do
39
+ class TestDefault
40
+ include MongoDoc::Attributes
41
+
42
+ key :with_default, :default => 'value'
43
+ end
44
+
45
+ let(:object) { TestDefault.new }
46
+
47
+ it "uses the default value" do
48
+ object.with_default.should == 'value'
49
+ end
50
+
51
+ it "only uses the default value once" do
52
+ object.with_default.should == 'value'
53
+ class << object
54
+ def _default_with_default
55
+ 'other value'
56
+ end
57
+ end
58
+ object.with_default.should == 'value'
59
+ end
60
+
61
+ it "does not set the default value if the setter is invoked first" do
62
+ object.with_default = nil
63
+ object.with_default.should be_nil
64
+ end
65
+ end
66
+
67
+ context "specified type" do
68
+ class TestType
69
+ include MongoDoc::Attributes
70
+
71
+ key :birthdate, :type => Date
72
+ end
73
+
74
+ let(:object) { TestType.new }
75
+
76
+ it "does not call Type.cast_from_string when the set value is not a string" do
77
+ Date.should_not_receive :cast_from_string
78
+ object.birthdate = Date.today
79
+ end
80
+
81
+ context "when the accessor is set with a string" do
82
+ let(:date) { Date.today }
83
+
84
+ it "delegates to Type.cast_from_string to set the value" do
85
+ Date.should_receive(:cast_from_string).with(date.to_s)
86
+ object.birthdate = date.to_s
87
+ end
88
+
89
+ it "sets the value to the result of the case" do
90
+ object.birthdate = date.to_s
91
+ object.birthdate.should == date
92
+ end
93
+ end
94
+ end
95
+
40
96
  describe "used with inheritance" do
41
97
  class TestParent
42
- include MongoDoc::Document
98
+ include MongoDoc::Attributes
43
99
 
44
100
  key :parent_attr
45
101
  end
@@ -17,6 +17,14 @@ describe "MongoDoc::Collection" do
17
17
  MongoDoc::Collection.new('collection_name')
18
18
  end
19
19
 
20
+ it "has Criteria mixed in" do
21
+ MongoDoc::Criteria.should === collection
22
+ end
23
+
24
+ it "#collection references self for Mongo context" do
25
+ collection.send(:collection).should == collection
26
+ end
27
+
20
28
  %w([] clear count create_index db distinct drop drop_index drop_indexes group hint index_information map_reduce mapreduce name options pk_factory remove rename size).each do |delegated_method|
21
29
  it "delegates #{delegated_method} to the Mongo::Collection" do
22
30
  mongo_collection.should_receive(delegated_method)
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "MongoDoc::Contexts::MongoDoc" do
3
+ describe "MongoDoc::Contexts::Mongo" do
4
4
 
5
5
  class Address
6
6
  include MongoDoc::Document
@@ -2,27 +2,55 @@ require "spec_helper"
2
2
 
3
3
  describe MongoDoc::Contexts do
4
4
 
5
+ class ContextTest
6
+ include MongoDoc::Document
7
+
8
+ has_many :children
9
+ end
10
+
5
11
  context ".context_for" do
6
12
  let(:criteria) { stub('criteria', :klass => klass) }
7
13
 
8
14
  context "when criteria is for a top-level MongoDoc::Document" do
9
- let(:klass) { stub('klass', :collection => stub('collection')) }
15
+ let(:klass) { ContextTest }
10
16
 
11
- it "creates a MongoDoc context" do
17
+ it "creates a Mongo context" do
12
18
  MongoDoc::Contexts::Mongo.should_receive(:new).with(criteria)
13
19
  Mongoid::Contexts.context_for(criteria)
14
20
  end
15
21
  end
16
22
 
17
- context "when criteria is for an embedded MongoDoc::Document" do
18
- let(:klass) { stub('klass') }
23
+ context "when criteria is for an association" do
24
+ let(:klass) { ContextTest.new.children }
19
25
 
20
26
  it "creates an Enumerable context" do
21
27
  MongoDoc::Contexts::Enumerable.should_receive(:new).with(criteria)
22
28
  Mongoid::Contexts.context_for(criteria)
23
29
  end
24
30
  end
25
- end
26
31
 
32
+ context "when criteria is for a MongoDoc::Collection" do
33
+ let(:klass) { MongoDoc::Collection.new('collection') }
34
+
35
+ before do
36
+ MongoDoc::Collection.stub(:mongo_collection).and_return(stub('collection'))
37
+ end
38
+
39
+ it "creates a Mongo context" do
40
+ MongoDoc::Contexts::Mongo.should_receive(:new).with(criteria)
41
+ Mongoid::Contexts.context_for(criteria)
42
+ end
43
+ end
44
+
45
+ context "when criteria is not recognized" do
46
+ let(:klass) { Object }
47
+
48
+ it "raises an exception" do
49
+ expect do
50
+ Mongoid::Contexts.context_for(criteria)
51
+ end.should raise_error(Mongoid::Contexts::UnknownContext)
52
+ end
53
+ end
54
+ end
27
55
  end
28
56
 
@@ -4,16 +4,41 @@ describe MongoDoc::Criteria do
4
4
 
5
5
  class CriteriaTest
6
6
  extend MongoDoc::Criteria
7
+
8
+ def self.collection; end
7
9
  end
8
10
 
9
11
  context ".criteria" do
10
- it "creates a new criteria for the document" do
11
- CriteriaTest.criteria.should be_a_kind_of(Mongoid::Criteria)
12
+ it "creates a new CriteriaWrapper for the document" do
13
+ CriteriaTest.criteria.should be_a_kind_of(MongoDoc::Criteria::CriteriaWrapper)
14
+ end
15
+ end
16
+
17
+ context "CriteriaWrapper" do
18
+ let(:wrapper) { MongoDoc::Criteria::CriteriaWrapper.new(CriteriaTest) }
19
+
20
+ it "is a Criteria" do
21
+ Mongoid::Criteria.should === wrapper
12
22
  end
13
23
 
14
24
  it "sets the criteria klass" do
15
- CriteriaTest.criteria.klass.should == CriteriaTest
25
+ wrapper.klass.should == CriteriaTest
26
+ end
27
+
28
+ %w(all and any_in cache enslave excludes fuse in limit offset only order_by skip where).each do |wrapping_method|
29
+ it "#{wrapping_method} returns a new CriteriaWrapper" do
30
+ wrapper.send(wrapping_method).object_id.should_not == wrapper.object_id
31
+ end
32
+ end
33
+
34
+ it "extras returns a new CriteriaWrapper" do
35
+ wrapper.extras({}).object_id.should_not == wrapper.object_id
16
36
  end
37
+
38
+ it "not_in returns a new CriteriaWrapper" do
39
+ wrapper.not_in({}).object_id.should_not == wrapper.object_id
40
+ end
41
+
17
42
  end
18
43
 
19
44
  context "criteria delegates" do
@@ -23,11 +48,22 @@ describe MongoDoc::Criteria do
23
48
  CriteriaTest.stub(:criteria).and_return(criteria)
24
49
  end
25
50
 
26
- %w(and cache enslave excludes extras id in limit not_in offset only order_by page per_page skip where).each do |criteria_op|
51
+ %w(aggregate all and any_in blank? count empty? excludes extras first group id in last limit max min not_in offset one only order_by page paginate per_page skip sum where).each do |criteria_op|
27
52
  it "#{criteria_op} delegates to the criteria" do
28
53
  criteria.should_receive(criteria_op)
29
54
  CriteriaTest.send(criteria_op)
30
55
  end
31
56
  end
32
57
  end
58
+
59
+ context "criteria are reusable" do
60
+ it "creates a new instance on each invocation" do
61
+ original = CriteriaTest.any_in(:name => 'Les Hill')
62
+ chained = original.only(:name)
63
+ original.should_not == chained
64
+ end
65
+ end
66
+
67
+
68
+
33
69
  end
@@ -33,24 +33,9 @@ describe "MongoDoc::Document" do
33
33
  end
34
34
  end
35
35
 
36
- context "attributes" do
37
- it "has an initialize method that takes a hash" do
38
- data = 'data'
39
- FormForTest.new(:data => data).data.should == data
40
- end
41
-
42
- it "can set attributes from a hash" do
43
- test = FormForTest.new
44
- data = 'data'
45
- test.attributes = {:data => data}
46
- test.data.should == data
47
- end
48
-
49
- it "returns all its attributes" do
50
- data = 'data'
51
- test = FormForTest.new(:data => data)
52
- test.attributes.should == {:data => data}
53
- end
36
+ it "#initialize takes a hash" do
37
+ data = 'data'
38
+ FormForTest.new(:data => data).data.should == data
54
39
  end
55
40
  end
56
41
 
@@ -238,8 +223,8 @@ describe "MongoDoc::Document" do
238
223
  CreateTest.stub(:new).and_return(instance)
239
224
  end
240
225
 
241
- it "calls save on the instance with safe => false" do
242
- instance.should_receive(:save).with(false)
226
+ it "calls save on the instance with validate => true" do
227
+ instance.should_receive(:save).with(true)
243
228
  CreateTest.create(:data => data)
244
229
  end
245
230
 
@@ -261,7 +246,7 @@ describe "MongoDoc::Document" do
261
246
  end
262
247
 
263
248
  it "calls save! on the instance" do
264
- instance.should_receive(:save!)
249
+ instance.should_receive(:save!).with(no_args)
265
250
  CreateTest.create!(:data => data)
266
251
  end
267
252
 
data/spec/ext_spec.rb ADDED
@@ -0,0 +1,81 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe "Ruby Object Extensions" do
4
+ context "Conversions" do
5
+ context "Boolean" do
6
+ it "converts from a '1' to true" do
7
+ Boolean.cast_from_string('1').should be_true
8
+ end
9
+
10
+ it "converts from a 'tRuE' to true" do
11
+ Boolean.cast_from_string('tRuE').should be_true
12
+ end
13
+
14
+ it "converts anything else to false" do
15
+ Boolean.cast_from_string('0').should be_false
16
+ end
17
+ end
18
+
19
+ context "Date" do
20
+ it "returns nil for a blank string" do
21
+ Date.cast_from_string('').should be_nil
22
+ end
23
+
24
+ it "converts from a string to a Date" do
25
+ date = Date.today
26
+ Date.cast_from_string(date.to_s).should == date
27
+ end
28
+ end
29
+
30
+ context "DateTime" do
31
+ it "returns nil for a blank string" do
32
+ DateTime.cast_from_string('').should be_nil
33
+ end
34
+
35
+ it "converts from a string to a DateTime" do
36
+ datetime = DateTime.now
37
+ DateTime.cast_from_string(datetime.to_s).should === datetime
38
+ end
39
+ end
40
+
41
+ context "Numeric" do
42
+ context "BigDecimal" do
43
+ it "returns nil for a blank string" do
44
+ BigDecimal.cast_from_string('').should be_nil
45
+ end
46
+
47
+ it "converts from a string to a BigDecimal" do
48
+ big_decimal = BigDecimal.new("123")
49
+ BigDecimal.cast_from_string(big_decimal.to_s).should == big_decimal
50
+ end
51
+ end
52
+
53
+ context "Integer" do
54
+ it "returns nil for a blank string" do
55
+ Integer.cast_from_string('').should be_nil
56
+ end
57
+
58
+ it "converts from a string to a Bignum" do
59
+ big_number = 1000000000000
60
+ Integer.cast_from_string(big_number.to_s).should == big_number
61
+ end
62
+
63
+ it "converts from a string to a Fixnum" do
64
+ fixnum = 1
65
+ Integer.cast_from_string(fixnum.to_s).should == fixnum
66
+ end
67
+ end
68
+ end
69
+
70
+ context "Time" do
71
+ it "returns nil for a blank string" do
72
+ Time.cast_from_string('').should be_nil
73
+ end
74
+
75
+ it "converts from a string to a Time" do
76
+ time = Time.now
77
+ Time.cast_from_string(time.to_s).to_s.should == time.to_s
78
+ end
79
+ end
80
+ end
81
+ end
data/spec/finders_spec.rb CHANGED
@@ -58,16 +58,4 @@ describe MongoDoc::Finders do
58
58
  end
59
59
  end
60
60
 
61
- context "all other finders" do
62
- before do
63
- FindersTest.stub(:criteria).and_return(criteria)
64
- end
65
-
66
- %w(count first last).each do |which|
67
- it "calls #{which} on the new criteria" do
68
- criteria.should_receive(which)
69
- FindersTest.send(which)
70
- end
71
- end
72
- end
73
61
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 3
8
- - 1
9
- version: 0.3.1
8
+ - 2
9
+ version: 0.3.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Les Hill
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-06 00:00:00 -05:00
17
+ date: 2010-03-11 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -134,6 +134,7 @@ files:
134
134
  - data/.gitignore
135
135
  - examples/simple_document.rb
136
136
  - examples/simple_object.rb
137
+ - features/collections.feature
137
138
  - features/finders.feature
138
139
  - features/mongodb.yml
139
140
  - features/mongodoc_base.feature
@@ -153,7 +154,9 @@ files:
153
154
  - features/step_definitions/query_steps.rb
154
155
  - features/step_definitions/removing_documents_steps.rb
155
156
  - features/step_definitions/scope_steps.rb
157
+ - features/step_definitions/string_casting_steps.rb
156
158
  - features/step_definitions/util_steps.rb
159
+ - features/string_casting.feature
157
160
  - features/support/support.rb
158
161
  - features/using_criteria.feature
159
162
  - lib/mongo_doc.rb
@@ -172,6 +175,7 @@ files:
172
175
  - lib/mongo_doc/criteria.rb
173
176
  - lib/mongo_doc/cursor.rb
174
177
  - lib/mongo_doc/document.rb
178
+ - lib/mongo_doc/ext.rb
175
179
  - lib/mongo_doc/ext/array.rb
176
180
  - lib/mongo_doc/ext/binary.rb
177
181
  - lib/mongo_doc/ext/boolean_class.rb
@@ -221,6 +225,7 @@ files:
221
225
  - spec/associations/collection_proxy_spec.rb
222
226
  - spec/associations/document_proxy_spec.rb
223
227
  - spec/associations/hash_proxy_spec.rb
228
+ - spec/attributes_accessor_spec.rb
224
229
  - spec/attributes_spec.rb
225
230
  - spec/bson_matchers.rb
226
231
  - spec/bson_spec.rb
@@ -235,6 +240,7 @@ files:
235
240
  - spec/document_ext.rb
236
241
  - spec/document_spec.rb
237
242
  - spec/embedded_save_spec.rb
243
+ - spec/ext_spec.rb
238
244
  - spec/finders_spec.rb
239
245
  - spec/hash_matchers.rb
240
246
  - spec/matchers_spec.rb
@@ -279,6 +285,7 @@ test_files:
279
285
  - spec/associations/collection_proxy_spec.rb
280
286
  - spec/associations/document_proxy_spec.rb
281
287
  - spec/associations/hash_proxy_spec.rb
288
+ - spec/attributes_accessor_spec.rb
282
289
  - spec/attributes_spec.rb
283
290
  - spec/bson_matchers.rb
284
291
  - spec/bson_spec.rb
@@ -293,6 +300,7 @@ test_files:
293
300
  - spec/document_ext.rb
294
301
  - spec/document_spec.rb
295
302
  - spec/embedded_save_spec.rb
303
+ - spec/ext_spec.rb
296
304
  - spec/finders_spec.rb
297
305
  - spec/hash_matchers.rb
298
306
  - spec/matchers_spec.rb