Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

More initial changes.

  • Loading branch information...
commit 61bd7d91051fbb958478e2cb018bad677d397f0e 1 parent c59c151
Blake Gentry authored
View
10 remarkable_datamapper/lib/remarkable_datamapper/base.rb
@@ -64,7 +64,7 @@ def assert_good_or_bad_if_key(key, value, message_key=:message) #:nodoc:
# Default allow_nil? validation. It accepts the message_key which is
# the key which contain the message in @options.
#
- # It also gets an allow_nil message on remarkable.active_record.allow_nil
+ # It also gets an allow_nil message on remarkable.data_mapper.allow_nil
# to be used as default.
#
def allow_nil?(message_key=:message) #:nodoc:
@@ -74,7 +74,7 @@ def allow_nil?(message_key=:message) #:nodoc:
# Default allow_blank? validation. It accepts the message_key which is
# the key which contain the message in @options.
#
- # It also gets an allow_blank message on remarkable.active_record.allow_blank
+ # It also gets an allow_blank message on remarkable.data_mapper.allow_blank
# to be used as default.
#
def allow_blank?(message_key=:message) #:nodoc:
@@ -93,7 +93,7 @@ def bad?(value, message_sym=:message) #:nodoc:
assert_bad_value(@subject, @attribute, value, @options[message_sym])
end
- # Asserts that an Active Record model validates with the passed
+ # Asserts that a DataMapper model validates with the passed
# <tt>value</tt> by making sure the <tt>error_message_to_avoid</tt> is not
# contained within the list of errors for that attribute.
#
@@ -119,7 +119,7 @@ def assert_good_value(model, attribute, value, error_message_to_avoid=//) # :nod
assert_does_not_contain(model.errors.on(attribute), error_message_to_avoid)
end
- # Asserts that an Active Record model invalidates the passed
+ # Asserts that a DataMapper model invalidates the passed
# <tt>value</tt> by making sure the <tt>error_message_to_expect</tt> is
# contained within the list of errors for that attribute.
#
@@ -173,7 +173,7 @@ def assert_bad_value(model, attribute, value, error_message_to_expect=:invalid)
# macros would start to pass when they shouldn't.
#
# Using the underlying mechanism inside DataMapper makes us free from
- # all thos errors.
+ # all those errors.
#
# We replace {{count}} interpolation for 12345 which later is replaced
# by a regexp which contains \d+.
View
233 remarkable_datamapper/lib/remarkable_datamapper/matchers/validates_is_unique.rb
@@ -0,0 +1,233 @@
+module Remarkable
+ module DataMapper
+ module Matchers
+ class ValidatesIsUniqueMatcher < Remarkable::DataMapper::Base #:nodoc:
+ arguments :collection => :attributes, :as => :attribute
+
+ optional :message
+ optional :scope, :splat => true
+ optional :case_sensitive, :allow_nil, :allow_blank, :default => true
+
+ collection_assertions :find_first_object?, :responds_to_scope?, :is_unique?, :case_sensitive?,
+ :valid_with_new_scope?, :allow_nil?, :allow_blank?
+
+ default_options :message => :taken
+
+ before_assert do
+ @options[:scope] = [*@options[:scope]].compact if @options[:scope]
+ end
+
+ private
+
+ # Tries to find an object in the database. If allow_nil and/or allow_blank
+ # is given, we must find a record which is not nil or not blank.
+ #
+ # We should also ensure that the object retrieved from the database
+ # is not the @subject.
+ #
+ # 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
+ [ [], "" ]
+ 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)}'"
+ end
+
+ options = conditions.empty? ? {} : { :conditions => conditions.join(' AND ') }
+
+ return true if @existing = subject_class.find(:first, options)
+ raise ScriptError, "could not find a #{subject_class} record in the database" + message
+ end
+
+ # Set subject scope to be equal to the object found.
+ #
+ def responds_to_scope?
+ (@options[:scope] || []).each do |scope|
+ setter = :"#{scope}="
+
+ return false, :method => setter unless @subject.respond_to?(setter)
+ return false, :method => scope unless @existing.respond_to?(scope)
+
+ @subject.send(setter, @existing.send(scope))
+ end
+ true
+ end
+
+ # Check if the attribute given is valid and if the validation fails for equal values.
+ #
+ def is_unique?
+ @value = @existing.send(@attribute)
+ 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?
+ (@options[:scope] || []).each do |scope|
+ setter = :"#{scope}="
+
+ previous_scope_value = @subject.send(scope)
+ @subject.send(setter, new_value_for_scope(scope))
+ return false, :method => scope unless good?(@value)
+
+ @subject.send(setter, previous_scope_value)
+ end
+ true
+ end
+
+ # Change the existing object attribute to nil to run allow nil
+ # validations. If we find any problem while updating the @existing
+ # record, it's because we can't save nil values in the database. So it
+ # passes when :allow_nil is false, but should raise an error when
+ # :allow_nil is true
+ #
+ def allow_nil?
+ return true unless @options.key?(:allow_nil)
+
+ begin
+ @existing.update_attribute(@attribute, nil)
+ rescue ::ActiveRecord::StatementInvalid => e
+ raise ScriptError, "You declared that #{@attribute} accepts nil values in validate_uniqueness_of, " <<
+ "but I cannot save nil values in the database, got: #{e.message}" if @options[:allow_nil]
+ return true
+ end
+
+ super
+ end
+
+ # Change the existing object attribute to blank to run allow blank
+ # validation. It uses the same logic as :allow_nil.
+ #
+ def allow_blank?
+ return true unless @options.key?(:allow_blank)
+
+ begin
+ @existing.update_attribute(@attribute, '')
+ rescue ::ActiveRecord::StatementInvalid => e
+ raise ScriptError, "You declared that #{@attribute} accepts blank values in validate_uniqueness_of, " <<
+ "but I cannot save blank values in the database, got: #{e.message}" if @options[:allow_blank]
+ return true
+ end
+
+ super
+ end
+
+ # Returns a value to be used as new scope. It deals with four different
+ # cases: date, time, boolean and stringfiable (everything that can be
+ # converted to a string and the next value makes sense)
+ #
+ def new_value_for_scope(scope)
+ column_type = if @existing.respond_to?(:column_for_attribute)
+ @existing.column_for_attribute(scope)
+ else
+ nil
+ end
+
+ case column_type.type
+ when :int, :integer, :float, :decimal
+ new_value_for_stringfiable_scope(scope)
+ when :datetime, :timestamp, :time
+ Time.now + 10000
+ when :date
+ Date.today + 100
+ when :boolean
+ !@existing.send(scope)
+ else
+ new_value_for_stringfiable_scope(scope)
+ end
+ end
+
+ # Returns a value to be used as scope by generating a range of values
+ # and searching for them in the database.
+ #
+ def new_value_for_stringfiable_scope(scope)
+ values = [(@existing.send(scope) || 999).next.to_s]
+
+ # Generate a range of values to search in the database
+ 100.times do
+ values << values.last.next
+ end
+ 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.map!{ |r| r.send(scope).to_s }
+
+ if value_to_return = (values - db_values).first
+ value_to_return
+ else
+ raise ScriptError, "Tried to find an unique scope value for #{scope} but I could not. " <<
+ "The conditions hash was #{conditions.inspect} and it returned all records."
+ end
+ end
+ end
+
+ # Ensures that the model cannot be saved if one of the attributes listed
+ # is not unique.
+ #
+ # Requires an existing record in the database. If you supply :allow_nil as
+ # option, you need to have in the database a record which is not nil in the
+ # given attributes. The same is required for allow_blank option.
+ #
+ # Notice that the record being validate should not be the same as in the
+ # database. In other words, you can't do this:
+ #
+ # subject { Post.create!(@valid_attributes) }
+ # should_validate_uniqueness_of :title
+ #
+ # But don't worry, if you eventually do that, a helpful error message
+ # will be raised.
+ #
+ # == 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>.
+ # Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.taken')</tt>
+ #
+ # == Examples
+ #
+ # it { should validate_uniqueness_of(:keyword, :username) }
+ # it { should validate_uniqueness_of(:email, :scope => :name, :case_sensitive => false) }
+ # 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 :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)
+ end
+ end
+ end
+end
View
264 remarkable_datamapper/locale/en.yml
@@ -0,0 +1,264 @@
+en:
+ remarkable:
+ data_mapper:
+ describe:
+ each: "{{key}} is {{value}}"
+ prepend: "when "
+ connector: " and "
+ expectations:
+ allow_nil: "{{subject_name}} to {{not}}allow nil values for {{attribute}}"
+ allow_blank: "{{subject_name}} to {{not}}allow blank values for {{attribute}}"
+ optionals:
+ allow_nil:
+ positive: "allowing nil values"
+ negative: "not allowing nil values"
+ allow_blank:
+ positive: "allowing blank values"
+ negative: "not allowing blank values"
+
+ accept_nested_attributes_for:
+ description: "accept nested attributes for {{associations}}"
+ expectations:
+ association_exists: "{{subject_name}} to have association {{association}}, but does not"
+ is_autosave: "{{subject_name}} to have association {{association}} with autosave true, got false"
+ responds_to_attributes: "{{subject_name}} to respond to :{{association}}_attributes=, but does not"
+ allows_destroy: "{{subject_name}} with allow destroy equals to {{allow_destroy}}, got {{actual}}"
+ accepts: "{{subject_name}} to accept attributes {{attributes}} for {{association}}, but does not"
+ rejects: "{{subject_name}} to reject attributes {{attributes}} for {{association}}, but does not"
+ optionals:
+ allow_destroy:
+ positive: "allowing destroy"
+ negative: "not allowing destroy"
+ accept:
+ positive: "accepting {{sentence}}"
+ reject:
+ positive: "rejecting {{sentence}}"
+
+ allow_values_for:
+ description: "allow {{in}} as values for {{attributes}}"
+ expectations:
+ is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
+
+ allow_mass_assignment_of:
+ description: "allow mass assignment of {{attributes}}"
+ expectations:
+ allows: "{{subject_name}} to allow mass assignment ({{subject_name}} is protecting {{protected_attributes}})"
+ is_protected: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} is protecting {{attribute}})"
+ is_accessible: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} has not made {{attribute}} accessible)"
+ negative_expectations:
+ allows: "{{subject_name}} to allow mass assignment ({{subject_name}} made {{accessible_attributes}} accessible)"
+ is_protected: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} is not protecting {{attribute}})"
+ is_accessible: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} has made {{attribute}} accessible)"
+
+ association:
+ belongs_to: belong to
+ has_many: have many
+ has_and_belongs_to_many: have and belong to many
+ has_one: have one
+ description: "{{macro}} {{associations}}"
+ expectations:
+ association_exists: "{{subject_name}} records {{macro}} {{association}}, but the association does not exist"
+ macro_matches: "{{subject_name}} records {{macro}} {{association}}, got {{subject_name}} records {{actual_macro}} {{association}}"
+ through_exists: "{{subject_name}} records {{macro}} {{association}} through {{through}}, through association does not exist"
+ source_exists: "{{subject_name}} records {{macro}} {{association}} through {{through}}, source association does not exist"
+ klass_exists: "{{subject_name}} records {{macro}} {{association}}, but the association class does not exist"
+ join_table_exists: "join table {{join_table}} to exist, but does not"
+ foreign_key_exists: "foreign key {{foreign_key}} to exist on {{foreign_key_table}}, but does not"
+ polymorphic_exists: "{{subject_table}} to have {{polymorphic_column}} as column, but does not"
+ counter_cache_exists: "{{reflection_table}} to have {{counter_cache_column}} as column, but does not"
+ options_match: "{{subject_name}} records {{macro}} {{association}} with options {{options}}, got {{actual}}"
+ optionals:
+ through:
+ positive: "through {{value}}"
+ source:
+ positive: "with source {{inspect}}"
+ source_type:
+ positive: "with source type {{inspect}}"
+ class_name:
+ positive: "with class name {{inspect}}"
+ foreign_key:
+ positive: "with foreign key {{inspect}}"
+ dependent:
+ positive: "with dependent {{inspect}}"
+ join_table:
+ positive: "with join table {{inspect}}"
+ uniq:
+ positive: "with unique records"
+ negative: "without unique records"
+ readonly:
+ positive: "with readonly records"
+ negative: "without readonly records"
+ validate:
+ positive: "validating associated records"
+ negative: "not validating associated records"
+ autosave:
+ positive: "autosaving associated records"
+ negative: "not autosaving associated records"
+ as:
+ positive: "through the polymorphic interface {{inspect}}"
+ counter_cache:
+ positive: "with counter cache {{inspect}}"
+ negative: "without counter cache"
+ select:
+ positive: "selecting {{inspect}}"
+ conditions:
+ positive: "with conditions {{inspect}}"
+ include:
+ positive: "including {{inspect}}"
+ group:
+ positive: "grouping by {{inspect}}"
+ having:
+ positive: "having {{inspect}}"
+ order:
+ positive: "with order {{inspect}}"
+ limit:
+ positive: "with limit {{inspect}}"
+ offset:
+ positive: "with offset {{inspect}}"
+
+ have_column:
+ description: "have column(s) named {{columns}}"
+ expectations:
+ column_exists: "{{subject_name}} to have column named {{column}}"
+ options_match: "{{subject_name}} to have column {{column}} with options {{options}}, got {{actual}}"
+ optionals:
+ type:
+ positive: "with type {{inspect}}"
+ null:
+ positive: "allowing null values"
+ negative: "not allowing null values"
+ default:
+ positive: "with default value {{inspect}}"
+ negative: "with default value {{inspect}}"
+ limit:
+ positive: "with limit {{inspect}}"
+
+ have_default_scope:
+ description: "have a default scope with {{options}}"
+ expectations:
+ options_match: "default scope with {{options}}, got {{actual}}"
+
+ have_index:
+ description: "have index for column(s) {{columns}}"
+ expectations:
+ index_exists: "index {{column}} to exist on table {{table_name}}"
+ is_unique: "index on {{column}} with unique equals to {{unique}}, got {{actual}}"
+ optionals:
+ unique:
+ positive: "with unique values"
+ negative: "with non unique values"
+ table_name:
+ positive: "on table {{value}}"
+
+ have_readonly_attributes:
+ description: "make {{attributes}} read-only"
+ expectations:
+ is_readonly: "{{subject_name}} to make {{attribute}} read-only, got {{actual}}"
+
+ have_scope:
+ description: "have to scope itself to {{options}} when {{scope_name}} is called"
+ expectations:
+ is_scope: "{{scope_name}} when called on {{subject_name}} return an instance of ActiveRecord::NamedScope::Scope"
+ options_match: "{{scope_name}} when called on {{subject_name}} scope to {{options}}, got {{actual}}"
+ optionals:
+ with:
+ positive: "with {{inspect}} as argument"
+
+ validate_acceptance_of:
+ description: "require {{attributes}} to be accepted"
+ expectations:
+ requires_acceptance: "{{subject_name}} to be invalid if {{attribute}} is not accepted"
+ accept_is_valid: "{{subject_name}} to be valid when {{attribute}} is accepted with value {{accept}}"
+ optionals:
+ accept:
+ positive: "with value {{inspect}}"
+
+ validate_associated:
+ description: "require associated {{associations}} to be valid"
+ expectations:
+ is_valid: "{{subject_name}} to be invalid when {{association}} is invalid"
+
+ validate_confirmation_of:
+ description: "require {{attributes}} to be confirmed"
+ expectations:
+ responds_to_confirmation: "{{subject_name}} instance responds to {{attribute}}_confirmation"
+ confirms: "{{subject_name}} to be valid only when {{attribute}} is confirmed"
+
+ validate_exclusion_of:
+ description: "ensure exclusion of {{attributes}} in {{in}}"
+ expectations:
+ is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
+ is_invalid: "{{subject_name}} to be invalid when {{attribute}} is set to {{value}}"
+
+ validate_inclusion_of:
+ description: "ensure inclusion of {{attributes}} in {{in}}"
+ expectations:
+ is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
+ is_invalid: "{{subject_name}} to be invalid when {{attribute}} is set to {{value}}"
+
+ validate_length_of:
+ description: "ensure length of {{attributes}}"
+ expectations:
+ less_than_min_length: "{{subject_name}} to be invalid when {{attribute}} length is less than {{minimum}} characters"
+ exactly_min_length: "{{subject_name}} to be valid when {{attribute}} length is {{minimum}} characters"
+ more_than_max_length: "{{subject_name}} to be invalid when {{attribute}} length is more than {{maximum}} characters"
+ exactly_max_length: "{{subject_name}} to be valid when {{attribute}} length is {{maximum}} characters"
+ optionals:
+ within:
+ positive: "is within {{inspect}} characters"
+ maximum:
+ positive: "is maximum {{inspect}} characters"
+ minimum:
+ positive: "is minimum {{inspect}} characters"
+ is:
+ positive: "is equal to {{inspect}} characters"
+ with_kind_of:
+ positive: "with kind of {{value}}"
+
+ validate_numericality_of:
+ description: "ensure numericality of {{attributes}}"
+ expectations:
+ only_numeric_values: "{{subject_name}} to allow only numeric values for {{attribute}}"
+ only_integer: "{{subject_name}} to {{not}}allow only integer values for {{attribute}}"
+ only_even: "{{subject_name}} to allow only even values for {{attribute}}"
+ only_odd: "{{subject_name}} to allow only odd values for {{attribute}}"
+ equals_to: "{{subject_name}} to be valid only when {{attribute}} is equal to {{count}}"
+ more_than_maximum: "{{subject_name}} to be invalid when {{attribute}} is greater than {{count}}"
+ less_than_minimum: "{{subject_name}} to be invalid when {{attribute}} is less than {{count}}"
+ optionals:
+ only_integer:
+ positive: "allowing only integer values"
+ odd:
+ positive: "allowing only odd values"
+ even:
+ positive: "allowing only even values"
+ equal_to:
+ positive: "is equal to {{inspect}}"
+ less_than:
+ positive: "is less than {{inspect}}"
+ greater_than:
+ positive: "is greater than {{inspect}}"
+ less_than_or_equal_to:
+ positive: "is less than or equal to {{inspect}}"
+ greater_than_or_equal_to:
+ positive: "is greater than or equal to {{inspect}}"
+
+ validate_presence_of:
+ description: "require {{attributes}} to be set"
+ 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"
+
View
104 remarkable_datamapper/spec/model_builder.rb
@@ -0,0 +1,104 @@
+# This is based on Shoulda model builder for Test::Unit.
+#
+
+# TODO: !!! These functions are
+module ModelBuilder
+ def self.included(base)
+ return unless base.name =~ /^Spec/
+
+ base.class_eval do
+ after(:each) do
+ if @defined_constants
+ @defined_constants.each do |class_name|
+ Object.send(:remove_const, class_name)
+ 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
+ end
+ end
+
+ base.extend ClassMethods
+ end
+
+ def create_table(table_name, &block)
+ connection = ActiveRecord::Base.connection
+
+ begin
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
+ connection.create_table(table_name, &block)
+ @created_tables ||= []
+ @created_tables << table_name
+ connection
+ rescue Exception => e
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
+ raise e
+ end
+ end
+
+ def define_constant(class_name, base, &block)
+ class_name = class_name.to_s.camelize
+
+ klass = Class.new(base)
+ Object.const_set(class_name, klass)
+
+ klass.class_eval(&block) if block_given?
+
+ @defined_constants ||= []
+ @defined_constants << class_name
+
+ klass
+ end
+
+ def define_model_class(class_name, &block)
+ define_constant(class_name, ActiveRecord::Base, &block)
+ end
+
+ 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)
+ instance = klass.new
+
+ self.class.subject { instance } if self.class.respond_to?(:subject)
+ instance
+ end
+
+ module ClassMethods
+ # This is a macro to run validations of boolean optionals such as :allow_nil
+ # and :allow_blank. This macro tests all scenarios. The specs must have a
+ # define_and_validate method defined.
+ #
+ def create_optional_boolean_specs(optional, base, options={})
+ base.describe "with #{optional} option" do
+ it { should define_and_validate(options.merge(optional => true)).send(optional) }
+ it { should define_and_validate(options.merge(optional => false)).send(optional, false) }
+ it { should_not define_and_validate(options.merge(optional => true)).send(optional, false) }
+ it { should_not define_and_validate(options.merge(optional => false)).send(optional) }
+ end
+ end
+
+ def create_message_specs(base)
+ base.describe "with message option" do
+ it { should define_and_validate(:message => 'valid_message').message('valid_message') }
+ it { should_not define_and_validate(:message => 'not_valid').message('valid_message') }
+ end
+ end
+ end
+
+end
+
View
2  remarkable_datamapper/spec/rcov.opts
@@ -0,0 +1,2 @@
+--exclude "spec/*,gems/*"
+--rails
View
4 remarkable_datamapper/spec/spec.opts
@@ -0,0 +1,4 @@
+--colour
+--format progress
+--loadby mtime
+--reverse
View
54 remarkable_datamapper/spec/spec_helper.rb
@@ -0,0 +1,54 @@
+# encoding: utf-8
+require 'rubygems'
+
+RAILS_VERSION = ENV['RAILS_VERSION'] || '2.3.3'
+DM_VERSION = '0.10.0'
+
+gem 'activesupport', RAILS_VERSION
+require 'active_support'
+
+gem 'addressable'
+require 'addressable/uri'
+
+gem 'data_objects', DM_VERSION
+require 'data_objects'
+
+gem 'do_sqlite3', DM_VERSION
+require 'do_sqlite3'
+
+gem 'rails_datamapper', DM_VERSION
+require 'rails_datamapper'
+
+gem 'dm-validations', DM_VERSION
+require 'dm-validations'
+
+ENV['SQLITE3_SPEC_URI'] ||= 'sqlite3::memory:'
+ENV['ADAPTER'] = 'sqlite3'
+
+# Configure DataMapper Adapter
+def setup_adapter(name, default_uri = nil)
+ begin
+ DataMapper.setup(name, ENV["#{ENV['ADAPTER'].to_s.upcase}_SPEC_URI"] || default_uri)
+ Object.const_set('ADAPTER', ENV['ADAPTER'].to_sym) if name.to_s == ENV['ADAPTER']
+ true
+ rescue Exception => e
+ if name.to_s == ENV['ADAPTER']
+ Object.const_set('ADAPTER', nil)
+ warn "Could not load do_#{name}: #{e}"
+ end
+ false
+ end
+end
+
+setup_adapter(:default)
+
+# Load Remarkable core on place to avoid gem to be loaded
+dir = File.dirname(__FILE__)
+require File.join(dir, '..', '..', 'remarkable', 'lib', 'remarkable')
+
+# Load Remarkable DataMapper
+require File.join(dir, 'model_builder')
+require File.join(dir, '..', 'lib', 'remarkable_datamapper')
+
+# Include matchers
+Remarkable.include_matchers!(Remarkable::DataMapper, Spec::Example::ExampleGroup)
Please sign in to comment.
Something went wrong with that request. Please try again.