mongo_odm 0.2.8 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,17 +5,24 @@ module MongoODM
5
5
 
6
6
  delegate :inspect, :to_xml, :to_yaml, :to_json, :include?, :to => :to_a
7
7
 
8
- def initialize(klass, selector = {}, opts = {})
9
- @klass, @selector, @opts = klass, selector, opts
8
+ def initialize(klass, options = {})
9
+ @klass = klass
10
+ @selector = options[:selector] || {}
11
+ @opts = options[:opts] || {}
12
+ @sort = options[:sort] || []
13
+ @limit = options[:limit] || nil
14
+ @skip = options[:skip] || nil
10
15
  _set_cursor
11
16
  end
12
- attr_reader :selector, :opts, :cursor
13
17
 
14
18
  def ==(other)
15
19
  case other
16
20
  when Criteria
17
- other.instance_variable_get("@selector") == @selector &&
18
- other.instance_variable_get("@opts") == @opts
21
+ other.instance_variable_get(:@selector) == @selector &&
22
+ other.instance_variable_get(:@opts) == @opts &&
23
+ other.instance_variable_get(:@sort) == @sort &&
24
+ other.instance_variable_get(:@limit) == @limit &&
25
+ other.instance_variable_get(:@skip) == @skip
19
26
  else
20
27
  to_a == other.to_a
21
28
  end
@@ -25,13 +32,24 @@ module MongoODM
25
32
  @cursor.to_a
26
33
  end
27
34
 
35
+ def to_cursor
36
+ @cursor
37
+ end
38
+
28
39
  def _set_cursor
29
40
  @cursor = @klass.collection.find(@selector, @opts)
41
+ @cursor = @cursor.sort(@sort) unless @sort.blank?
42
+ @cursor = @cursor.limit(@limit) unless @limit.blank?
43
+ @cursor = @cursor.skip(@skip) unless @skip.blank?
44
+ @cursor
30
45
  end
31
46
 
32
- def _merge_criteria(selector, opts)
33
- @selector.merge!(selector)
34
- @opts.merge!(opts)
47
+ def _merge_criteria(criteria)
48
+ @selector.merge!(criteria.instance_variable_get(:@selector))
49
+ @opts.merge!(criteria.instance_variable_get(:@opts))
50
+ @sort << criteria.instance_variable_get(:@sort) unless criteria.instance_variable_get(:@sort).blank?
51
+ @limit = criteria.instance_variable_get(:@limit) unless criteria.instance_variable_get(:@limit).blank?
52
+ @skip = criteria.instance_variable_get(:@skip) unless criteria.instance_variable_get(:@skip).blank?
35
53
  _set_cursor
36
54
  self
37
55
  end
@@ -39,7 +57,7 @@ module MongoODM
39
57
  def method_missing(method_name, *args, &block)
40
58
  if @klass.respond_to?(method_name)
41
59
  result = @klass.send(method_name, *args, &block)
42
- result.is_a?(Criteria) ? _merge_criteria(result.selector, result.opts) : result
60
+ result.is_a?(Criteria) ? _merge_criteria(result) : result
43
61
  elsif @cursor.respond_to?(method_name)
44
62
  @cursor.send(method_name, *args, &block)
45
63
  elsif [].respond_to?(method_name)
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
2
  module MongoODM
3
3
 
4
+ delegate :inspect, :to_xml, :to_yaml, :to_json, :include?, :to => :to_a
5
+
4
6
  class Cursor < Mongo::Cursor
5
7
  def next_document
6
8
  doc = super
@@ -88,18 +88,31 @@ module MongoODM
88
88
  end
89
89
  end
90
90
 
91
- def find(*args)
92
- if args.size == 1 && args.first.is_a?(String)
93
- MongoODM::Criteria.new(self, :_id => BSON::ObjectId.from_string(args.first))
94
- elsif args.size == 1 && args.first.is_a?(BSON::ObjectId)
95
- MongoODM::Criteria.new(self, :_id => args.first)
91
+ def find(selector = {}, opts = {})
92
+ if opts.blank? && selector.is_a?(String)
93
+ MongoODM::Criteria.new(self, :selector => {:_id => BSON::ObjectId.from_string(selector)})
94
+ elsif opts.blank? && selector.is_a?(BSON::ObjectId)
95
+ MongoODM::Criteria.new(self, :selector => {:_id => selector})
96
96
  else
97
- MongoODM::Criteria.new(self, *args)
97
+ MongoODM::Criteria.new(self, :selector => selector, :opts => opts)
98
98
  end
99
99
  end
100
100
 
101
+ def sort(key_or_list, direction = nil)
102
+ order = key_or_list.is_a?(Array) ? key_or_list : direction.nil? ? [key_or_list, :asc] : [key_or_list, direction]
103
+ MongoODM::Criteria.new(self, :sort => order)
104
+ end
105
+
106
+ def skip(number_to_skip = nil)
107
+ MongoODM::Criteria.new(self, :skip => number_to_skip)
108
+ end
109
+
110
+ def limit(number_to_return = nil)
111
+ MongoODM::Criteria.new(self, :limit => number_to_return)
112
+ end
113
+
101
114
  def cursor
102
- @cursor ||= find.cursor
115
+ @cursor ||= find.to_cursor
103
116
  end
104
117
 
105
118
  def destroy_all(*args)
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+ require 'active_support/core_ext/module/aliasing'
3
+
4
+ module MongoODM
5
+ module Document
6
+ module Validations
7
+ # Validates whether or not a field is unique against the documents in the
8
+ # database.
9
+ #
10
+ # @example Define the uniqueness validator.
11
+ #
12
+ # class Person
13
+ # include MongoODM::Document
14
+ # field :title
15
+ #
16
+ # validates_uniqueness_of :title
17
+ # end
18
+ class UniquenessValidator < ActiveModel::EachValidator
19
+
20
+ # Unfortunately, we have to tie Uniqueness validators to a class.
21
+ def setup(klass)
22
+ @klass = klass
23
+ end
24
+
25
+ # Validate the document for uniqueness violations.
26
+ #
27
+ # @example Validate the document.
28
+ # validate_each(person, :title, "Sir")
29
+ #
30
+ # @param [ Document ] document The document to validate.
31
+ # @param [ Symbol ] attribute The field to validate on.
32
+ # @param [ Object ] value The value of the field.
33
+ def validate_each(document, attribute, value)
34
+ criteria = @klass.find(attribute => unique_search_value(value))
35
+ unless document.new_record?
36
+ criteria = criteria.find(:_id => {'$ne' => document._id})
37
+ end
38
+
39
+ Array.wrap(options[:scope]).each do |item|
40
+ criteria = criteria.find(item => document.attributes[item])
41
+ end
42
+ if criteria.first
43
+ document.errors.add(
44
+ attribute,
45
+ :taken,
46
+ options.except(:case_sensitive, :scope).merge(:value => value)
47
+ )
48
+ end
49
+ end
50
+
51
+ protected
52
+
53
+ # ensure :case_sensitive is true by default
54
+ def unique_search_value(value)
55
+ if options[:case_sensitive]
56
+ value
57
+ else
58
+ value ? Regexp.new("^#{Regexp.escape(value.to_s)}$", Regexp::IGNORECASE) : nil
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -6,6 +6,9 @@ module MongoODM
6
6
  module Validations
7
7
 
8
8
  extend ActiveSupport::Concern
9
+ extend ActiveSupport::Autoload
10
+
11
+ autoload :UniquenessValidator
9
12
 
10
13
  included do
11
14
  include ActiveModel::Validations
@@ -38,6 +41,25 @@ module MongoODM
38
41
  errors.empty?
39
42
  end
40
43
  end
44
+
45
+ module ClassMethods
46
+ # Validates whether or not a field is unique against the documents in the
47
+ # database.
48
+ #
49
+ # @example
50
+ #
51
+ # class Person
52
+ # include MongoODM::Document
53
+ # field :title
54
+ #
55
+ # validates_uniqueness_of :title
56
+ # end
57
+ #
58
+ # @param [ Array ] *args The arguments to pass to the validator.
59
+ def validates_uniqueness_of(*args)
60
+ validates_with(UniquenessValidator, _merge_attributes(args))
61
+ end
62
+ end
41
63
 
42
64
  end
43
65
  end
@@ -2,6 +2,6 @@
2
2
  module MongoODM
3
3
  VERSION_MAJOR = "0"
4
4
  VERSION_MINOR = "2"
5
- VERSION_BUILD = "8"
5
+ VERSION_BUILD = "9"
6
6
  VERSION = "#{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_BUILD}"
7
7
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: mongo_odm
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.8
5
+ version: 0.2.9
6
6
  platform: ruby
7
7
  authors:
8
8
  - Carlos Paramio
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-02-20 00:00:00 +01:00
13
+ date: 2011-03-14 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -270,6 +270,7 @@ files:
270
270
  - lib/mongo_odm/document/persistence.rb
271
271
  - lib/mongo_odm/document/timestamps.rb
272
272
  - lib/mongo_odm/document/validations.rb
273
+ - lib/mongo_odm/document/validations/uniqueness_validator.rb
273
274
  - lib/mongo_odm/errors.rb
274
275
  - lib/mongo_odm/railtie.rb
275
276
  - lib/mongo_odm/version.rb