Skip to content

Commit

Permalink
Most of specs pass. Removed :case_sensitive and :allow_blank options …
Browse files Browse the repository at this point in the history
…because there is no equivalent in validates_is_unique
  • Loading branch information
Blake Gentry committed Sep 2, 2009
1 parent f2b79b5 commit 39c44f0
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 190 deletions.
13 changes: 6 additions & 7 deletions remarkable_datamapper/lib/remarkable_datamapper/base.rb
Expand Up @@ -180,12 +180,11 @@ def assert_bad_value(model, attribute, value, error_message_to_expect=:invalid)
#
def error_message_from_model(model, attribute, message) #:nodoc:
if message.is_a? Symbol
message = if I18N # Rails >= 2.2
model.errors.generate_message(attribute, message, :count => '12345')
else # Rails <= 2.1
::DataMapper::Errors.default_error_messages[message] % '12345'
end

# TODO: No Internationalization yet.
# TODO: remove debug line
pp attribute
message = ::DataMapper::Validate::ValidationErrors.default_error_message(message, attribute, '12345')

if message =~ /12345/
message = Regexp.escape(message)
message.gsub!('12345', '\d+')
Expand Down Expand Up @@ -240,7 +239,7 @@ def collection_interpolation #:nodoc:
# Returns true if the given collection should be translated.
#
def i18n_collection? #:nodoc:
I18N && I18N_COLLECTION.include?(self.class.matcher_arguments[:collection])
RAILS_I18N && I18N_COLLECTION.include?(self.class.matcher_arguments[:collection])
end

end
Expand Down
Expand Up @@ -130,7 +130,6 @@ def describe(*args, &block)
:key => translated_key.downcase, :value => value.inspect)
end

pp pieces
description << pieces.join(connector)
args.unshift(description)

Expand Down
@@ -1,15 +1,15 @@
module Remarkable
module DataMapper
module Matchers
class ValidatesIsUniqueMatcher < Remarkable::DataMapper::Base #:nodoc:
class ValidateIsUniqueMatcher < Remarkable::DataMapper::Base #:nodoc:
arguments :collection => :attributes, :as => :attribute

optional :message
optional :scope, :splat => true
optional :case_sensitive, :allow_nil, :allow_blank, :default => true
optional :nullable, :default => true

collection_assertions :find_first_object?, :responds_to_scope?, :is_unique?, :case_sensitive?,
:valid_with_new_scope?, :allow_nil?, :allow_blank?
collection_assertions :find_first_object?, :responds_to_scope?, :is_unique?,
:valid_with_new_scope?, :nullable?

default_options :message => :taken

Expand All @@ -28,24 +28,24 @@ class ValidatesIsUniqueMatcher < Remarkable::DataMapper::Base #:nodoc:
# If any of these attempts fail, an error is raised.
#
def find_first_object?
conditions, message = if @options[:allow_nil]
[ ["#{@attribute} IS NOT NULL"], " with #{@attribute} not nil" ]
elsif @options[:allow_blank]
[ ["#{@attribute} != ''"], " with #{@attribute} not blank" ]
else
[ [], "" ]
conditions, message = [[], ""]
if @options[:nullable]
conditions << {::DataMapper::Query::Operator.new(@attribute, :not) => nil}
message << " with #{@attribute} not nil"
end

unless @subject.new_record?
primary_key = subject_class.primary_key

message << " which is different from the subject record (the object being validated is the same as the one in the database)"
conditions << "#{subject_class.primary_key} != '#{@subject.send(primary_key)}'"

unless @subject.new?
key = subject_class.key

message << " which is different from the subject record (the object being validated is the same as the one in the database)"
conditions << {::DataMapper::Query::Operator.new(subject_class.key.first.name, :not) => @subject.send(key)}
pp conditions
end

options = conditions.empty? ? {} : { :conditions => conditions.join(' AND ') }

return true if @existing = subject_class.find(:first, options)

require 'pp'
#pp conditions

return true if @existing = subject_class.first(conditions)
raise ScriptError, "could not find a #{subject_class} record in the database" + message
end

Expand All @@ -70,19 +70,6 @@ def is_unique?
return bad?(@value)
end

# If :case_sensitive is given and it's false, we swap the case of the
# value used in :is_unique? and see if the test object remains valid.
#
# If :case_sensitive is given and it's true, we swap the case of the
# value used in is_unique? and see if the test object is not valid.
#
# This validation will only occur if the test object is a String.
#
def case_sensitive?
return true unless @value.is_a?(String)
assert_good_or_bad_if_key(:case_sensitive, @value.swapcase)
end

# Now test that the object is valid when changing the scoped attribute.
#
def valid_with_new_scope?
Expand Down Expand Up @@ -173,7 +160,7 @@ def new_value_for_stringfiable_scope(scope)
conditions = { scope => values, @attribute => @value }

# Get values from the database, get the scope attribute and map them to string.
db_values = subject_class.find(:all, :conditions => conditions, :select => scope)
db_values = subject_class.all(:conditions => conditions, :fields => [scope])
db_values.map!{ |r| r.send(scope).to_s }

if value_to_return = (values - db_values).first
Expand Down Expand Up @@ -204,7 +191,6 @@ def new_value_for_stringfiable_scope(scope)
# == Options
#
# * <tt>:scope</tt> - field(s) to scope the uniqueness to.
# * <tt>:case_sensitive</tt> - the matcher look for an exact match.
# * <tt>:allow_nil</tt> - when supplied, validates if it allows nil or not.
# * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
Expand All @@ -213,20 +199,19 @@ def new_value_for_stringfiable_scope(scope)
# == Examples
#
# it { should validate_uniqueness_of(:keyword, :username) }
# it { should validate_uniqueness_of(:email, :scope => :name, :case_sensitive => false) }
# it { should validate_uniqueness_of(:email, :scope => :name) }
# it { should validate_uniqueness_of(:address, :scope => [:first_name, :last_name]) }
#
# should_validate_uniqueness_of :keyword, :username
# should_validate_uniqueness_of :email, :scope => :name, :case_sensitive => false
# should_validate_uniqueness_of :email, :scope => :name
# should_validate_uniqueness_of :address, :scope => [:first_name, :last_name]
#
# should_validate_uniqueness_of :email do |m|
# m.scope = name
# m.case_sensitive = false
# end
#
def validates_is_unique(*attributes, &block)
ValidateUniquenessOfMatcher.new(*attributes, &block).spec(self)
def validate_is_unique(*attributes, &block)
ValidateIsUniqueMatcher.new(*attributes, &block).spec(self)
end
end
end
Expand Down
17 changes: 2 additions & 15 deletions remarkable_datamapper/locale/en.yml
Expand Up @@ -248,25 +248,12 @@ en:
expectations:
allow_nil: "{{subject_name}} to require {{attribute}} to be set"

validate_uniqueness_of:
description: "require unique values for {{attributes}}"
expectations:
responds_to_scope: "{{subject_name}} instance responds to {{method}}"
is_unique: "{{subject_name}} to require unique values for {{attribute}}"
case_sensitive: "{{subject_name}} to {{not}}be case sensitive on {{attribute}} validation"
valid_with_new_scope: "{{subject_name}} to be valid when {{attribute}} scope ({{method}}) change"
optionals:
scope:
positive: "scoped to {{sentence}}"
case_sensitive:
positive: "case sensitive"
negative: "case insensitive"

validates_is_unique:
validate_is_unique:
description: "require unique values for {{attributes}}"
expectations:
responds_to_scope: "{{subject_name}} instance responds to {{method}}"
is_unique: "{{subject_name}} to require unique values for {{attribute}}"
nullable: "{{subject_name}} to require {{attribute}} to be set"
case_sensitive: "{{subject_name}} to {{not}}be case sensitive on {{attribute}} validation"
valid_with_new_scope: "{{subject_name}} to be valid when {{attribute}} scope ({{method}}) change"
optionals:
Expand Down
103 changes: 0 additions & 103 deletions remarkable_datamapper/spec/describe_spec.rb

This file was deleted.

49 changes: 25 additions & 24 deletions remarkable_datamapper/spec/model_builder.rb
@@ -1,7 +1,7 @@
# This is based on Shoulda model builder for Test::Unit.
#

# TODO: !!! These functions are
# TODO: !!! These functions are not all updated yet
module ModelBuilder
def self.included(base)
return unless base.name =~ /^Spec/
Expand All @@ -14,29 +14,30 @@ def self.included(base)
end
end

DataMapper.auto_migrate!
#if @created_tables
# @created_tables.each do |table_name|
# ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{table_name}")
# end
#end
if @created_tables
@created_tables.each do |table_name|
DataMapper::Repository.adapters[:default].execute("DROP TABLE IF EXISTS #{table_name}")
end
end
end
end

base.extend ClassMethods
end

def create_table(table_name, &block)
connection = ActiveRecord::Base.connection
def create_table(model)
adapter = DataMapper::Repository.adapters[:default]
table_name = model.to_s.tableize
command = "DROP TABLE IF EXISTS #{table_name}"

begin
connection.execute("DROP TABLE IF EXISTS #{table_name}")
connection.create_table(table_name, &block)
adapter.execute(command)
adapter.create_model_storage(model)
@created_tables ||= []
@created_tables << table_name
connection
adapter
rescue Exception => e
connection.execute("DROP TABLE IF EXISTS #{table_name}")
adapter.execute(command)
raise e
end
end
Expand All @@ -45,8 +46,8 @@ def define_constant(class_name, base, &block)
class_name = class_name.to_s.camelize

klass = Class.new
klass.include base
Object.const_set(class_name, klass)
klass.send :include, base
Object.const_set(class_name, klass) #unless klass

klass.class_eval(&block) if block_given?

Expand All @@ -63,18 +64,18 @@ def define_model_class(class_name, &block)
def define_model(name, columns = {}, &block)
class_name = name.to_s.pluralize.classify
table_name = class_name.tableize

table = columns.delete(:table) || lambda {|table|
columns.each do |name, type|
table.column name, *type
end
}

create_table(table_name, &table)

klass = define_model_class(class_name, &block)
pp columns # TODO: REMOVE debug line
columns.each do |name, type|
options = {}
type, options = type if type.class == Array
klass.property(name, type, options)
end

instance = klass.new

create_table(klass)

self.class.subject { instance } if self.class.respond_to?(:subject)
instance
end
Expand Down

0 comments on commit 39c44f0

Please sign in to comment.