Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Views for unique validations created on loading, not execution

  • Loading branch information...
commit d56179aa6bd24bdcc39690e1f9b2007174723157 1 parent 938bf2c
Sam Lown samlown authored
1  history.md
View
@@ -10,6 +10,7 @@
* Removed railties dependency (DAddYE)
* DesignDoc cache refreshed if a database is deleted.
* Fixing dirty tracking on collection_of association.
+ * Uniqueness Validation views created on initialization, not on demand!
## 1.1.0.beta5 - 2011-04-30
43 lib/couchrest/model/validations/uniqueness.rb
View
@@ -3,7 +3,7 @@
module CouchRest
module Model
module Validations
-
+
# Validates if a field is unique
class UniquenessValidator < ActiveModel::EachValidator
@@ -11,29 +11,33 @@ class UniquenessValidator < ActiveModel::EachValidator
# or add one if necessary.
def setup(model)
@model = model
+ if options[:view].blank?
+ attributes.each do |attribute|
+ opts = merge_view_options(attribute)
+
+ if model.respond_to?(:has_view?) && !model.has_view?(opts[:view_name])
+ opts[:keys] << {:allow_nil => true}
+ model.view_by(*opts[:keys])
+ end
+ end
+ end
end
def validate_each(document, attribute, value)
- keys = [attribute]
- unless options[:scope].nil?
- keys = (options[:scope].is_a?(Array) ? options[:scope] : [options[:scope]]) + keys
- end
- values = keys.map{|k| document.send(k)}
- values = values.first if values.length == 1
+ opts = merge_view_options(attribute)
- view_name = options[:view].nil? ? "by_#{keys.join('_and_')}" : options[:view]
+ values = opts[:keys].map{|k| document.send(k)}
+ values = values.first if values.length == 1
model = (document.respond_to?(:model_proxy) && document.model_proxy ? document.model_proxy : @model)
# Determine the base of the search
- base = options[:proxy].nil? ? model : document.instance_eval(options[:proxy])
+ base = opts[:proxy].nil? ? model : document.instance_eval(opts[:proxy])
- if base.respond_to?(:has_view?) && !base.has_view?(view_name)
- raise "View #{document.class.name}.#{options[:view]} does not exist!" unless options[:view].nil?
- keys << {:allow_nil => true}
- model.view_by(*keys)
+ if base.respond_to?(:has_view?) && !base.has_view?(opts[:view_name])
+ raise "View #{document.class.name}.#{opts[:view_name]} does not exist for validation!"
end
- rows = base.view(view_name, :key => values, :limit => 2, :include_docs => false)['rows']
+ rows = base.view(opts[:view_name], :key => values, :limit => 2, :include_docs => false)['rows']
return if rows.empty?
unless document.new?
@@ -47,6 +51,17 @@ def validate_each(document, attribute, value)
end
end
+ private
+
+ def merge_view_options(attr)
+ keys = [attr]
+ keys.unshift(*options[:scope]) unless options[:scope].nil?
+
+ view_name = options[:view].nil? ? "by_#{keys.join('_and_')}" : options[:view]
+
+ options.merge({:keys => keys, :view_name => view_name})
+ end
+
end
end
19 spec/couchrest/validations_spec.rb
View
@@ -16,7 +16,11 @@
before(:all) do
@objs = ['title 1', 'title 2', 'title 3'].map{|t| WithUniqueValidation.create(:title => t)}
end
-
+
+ it "should create a new view if none defined before performing" do
+ WithUniqueValidation.has_view?(:by_title).should be_true
+ end
+
it "should validate a new unique document" do
@obj = WithUniqueValidation.create(:title => 'title 4')
@obj.new?.should_not be_true
@@ -35,6 +39,7 @@
@obj.should be_valid
end
+
it "should allow own view to be specified" do
# validates_uniqueness_of :code, :view => 'all'
WithUniqueValidationView.create(:title => 'title 1', :code => '1234')
@@ -50,6 +55,13 @@
}.should raise_error
end
+ it "should not try to create a defined view" do
+ WithUniqueValidationView.validates_uniqueness_of :title, :view => 'fooobar'
+ WithUniqueValidationView.has_view?('fooobar').should be_false
+ WithUniqueValidationView.has_view?('by_title').should be_false
+ end
+
+
it "should not try to create new view when already defined" do
@obj = @objs[1]
@obj.class.should_not_receive('view_by')
@@ -60,6 +72,11 @@
end
context "with a proxy parameter" do
+
+ it "should create a new view despite proxy" do
+ WithUniqueValidationProxy.has_view?(:by_title).should be_true
+ end
+
it "should be used" do
@obj = WithUniqueValidationProxy.new(:title => 'test 6')
proxy = @obj.should_receive('proxy').and_return(@obj.class)
Please sign in to comment.
Something went wrong with that request. Please try again.