Skip to content
Browse files

Merge branch 'master' of git://github.com/sam/dm-more

  • Loading branch information...
2 parents b429af7 + 0489eaa commit 7d5899260faa4aeba3b8623cec5dd219815ff7e8 Wesley Beary committed
Showing with 352 additions and 99 deletions.
  1. +1 −1 adapters/dm-couchdb-adapter/Rakefile
  2. +4 −3 adapters/dm-couchdb-adapter/lib/couchdb_adapter.rb
  3. +1 −1 adapters/dm-couchdb-adapter/lib/couchdb_adapter/version.rb
  4. +1 −1 adapters/dm-rest-adapter/Rakefile
  5. +3 −2 adapters/dm-rest-adapter/lib/rest_adapter.rb
  6. +1 −1 adapters/dm-rest-adapter/lib/rest_adapter/version.rb
  7. +1 −1 dm-adjust/Rakefile
  8. +4 −1 dm-adjust/lib/dm-adjust.rb
  9. +4 −2 dm-adjust/lib/dm-adjust/version.rb
  10. +1 −1 dm-aggregates/Rakefile
  11. +10 −8 dm-aggregates/lib/dm-aggregates.rb
  12. +4 −2 dm-aggregates/lib/dm-aggregates/version.rb
  13. +1 −1 dm-is-state_machine/TODO
  14. +4 −5 dm-is-state_machine/lib/dm-is-state_machine/is/data/event.rb
  15. +7 −7 dm-is-state_machine/lib/dm-is-state_machine/is/data/machine.rb
  16. +3 −3 dm-is-state_machine/lib/dm-is-state_machine/is/data/state.rb
  17. +1 −1 dm-is-state_machine/lib/dm-is-state_machine/is/dsl/event_dsl.rb
  18. +3 −3 dm-is-state_machine/lib/dm-is-state_machine/is/dsl/state_dsl.rb
  19. +6 −6 dm-is-state_machine/lib/dm-is-state_machine/is/state_machine.rb
  20. +1 −1 dm-is-state_machine/lib/dm-is-state_machine/is/version.rb
  21. +2 −2 dm-is-state_machine/spec/examples/invalid_events.rb
  22. +1 −1 dm-is-state_machine/spec/examples/invalid_states.rb
  23. +3 −3 dm-is-state_machine/spec/examples/invalid_transitions_1.rb
  24. +3 −3 dm-is-state_machine/spec/examples/invalid_transitions_2.rb
  25. +2 −2 dm-is-state_machine/spec/examples/traffic_light.rb
  26. +11 −11 dm-is-state_machine/spec/integration/traffic_light_spec.rb
  27. +3 −3 dm-is-state_machine/spec/unit/data/event_spec.rb
  28. +5 −5 dm-is-state_machine/spec/unit/data/machine_spec.rb
  29. +2 −2 dm-is-state_machine/spec/unit/data/state_spec.rb
  30. +3 −3 dm-is-state_machine/spec/unit/dsl/event_dsl_spec.rb
  31. +1 −1 dm-is-state_machine/spec/unit/dsl/state_dsl_spec.rb
  32. +3 −3 dm-is-state_machine/spec/unit/state_machine_spec.rb
  33. +3 −0 dm-types/Manifest.txt
  34. +7 −0 dm-types/lib/dm-types.rb
  35. +31 −0 dm-types/lib/dm-types/bcrypt_hash.rb
  36. +50 −0 dm-types/spec/integration/bcrypt_hash_spec.rb
  37. +50 −0 dm-types/spec/unit/bcrypt_hash_spec.rb
  38. +54 −8 dm-validations/lib/dm-validations/auto_validate.rb
  39. +49 −0 dm-validations/spec/integration/auto_validate_spec.rb
  40. +2 −1 merb_datamapper/lib/merb_datamapper.rb
  41. +6 −0 merb_datamapper/lib/merb_datamapper/merbtasks.rb
View
2 adapters/dm-couchdb-adapter/Rakefile
@@ -9,7 +9,7 @@ require ROOT + 'lib/couchdb_adapter/version'
AUTHOR = "Bernerd Schaefer"
EMAIL = "bj.schaefer@gmail.com"
GEM_NAME = "dm-couchdb-adapter"
-GEM_VERSION = DataMapper::Adapters::CouchDBAdapter::VERSION
+GEM_VERSION = DataMapper::More::CouchDBAdapter::VERSION
GEM_DEPENDENCIES = [["dm-core", GEM_VERSION]]
GEM_CLEAN = ["log", "pkg"]
GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO ] }
View
7 adapters/dm-couchdb-adapter/lib/couchdb_adapter.rb
@@ -1,10 +1,11 @@
require 'rubygems'
-gem 'dm-core', '=0.9.3'
-require 'base64'
+require 'pathname'
+require Pathname(__FILE__).dirname + 'couchdb_adapter/version'
+gem 'dm-core', DataMapper::More::CouchDBAdapter::VERSION
require 'dm-core'
+require 'base64'
require 'json'
require 'net/http'
-require 'pathname'
require 'uri'
require Pathname(__FILE__).dirname + 'couchdb_adapter/json_object'
require Pathname(__FILE__).dirname + 'couchdb_adapter/view'
View
2 adapters/dm-couchdb-adapter/lib/couchdb_adapter/version.rb
@@ -1,5 +1,5 @@
module DataMapper
- module Adapters
+ module More
class CouchDBAdapter
VERSION = "0.9.3"
end
View
2 adapters/dm-rest-adapter/Rakefile
@@ -9,7 +9,7 @@ require ROOT + 'lib/rest_adapter/version'
AUTHOR = "Potomac Ruby Hackers"
EMAIL = "potomac-ruby-hackers@googlegroups.com"
GEM_NAME = "dm-rest-adapter"
-GEM_VERSION = DataMapper::Adapters::RestAdapter::VERSION
+GEM_VERSION = DataMapper::More::RestAdapter::VERSION
GEM_DEPENDENCIES = [["dm-core", GEM_VERSION]]
GEM_CLEAN = ["log", "pkg"]
GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO ] }
View
5 adapters/dm-rest-adapter/lib/rest_adapter.rb
@@ -1,9 +1,10 @@
require 'rubygems'
-gem 'dm-core', '=0.9.3'
+require 'pathname'
+require Pathname(__FILE__).dirname + 'rest_adapter/version'
+gem 'dm-core', DataMapper::More::RestAdapter::VERSION
require 'dm-core'
require 'extlib'
require 'dm-serializer'
-require 'pathname'
require 'net/http'
require 'rexml/document'
View
2 adapters/dm-rest-adapter/lib/rest_adapter/version.rb
@@ -1,5 +1,5 @@
module DataMapper
- module Adapters
+ module More
class RestAdapter
VERSION = "0.9.3"
end
View
2 dm-adjust/Rakefile
@@ -9,7 +9,7 @@ require ROOT + 'lib/dm-adjust/version'
AUTHOR = "Sindre Aarsaether"
EMAIL = "sindre [a] identu [d] no"
GEM_NAME = "dm-adjust"
-GEM_VERSION = DataMapper::Adjust::VERSION
+GEM_VERSION = DataMapper::More::Adjust::VERSION
GEM_DEPENDENCIES = [["dm-core", GEM_VERSION]]
GEM_CLEAN = ["log", "pkg"]
GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO ] }
View
5 dm-adjust/lib/dm-adjust.rb
@@ -1,6 +1,9 @@
require 'rubygems'
+require 'pathname'
-gem 'dm-core', '=0.9.3'
+require Pathname(__FILE__).dirname + 'dm-adjust/version'
+
+gem 'dm-core', DataMapper::More::Adjust::VERSION
require 'dm-core'
dir = Pathname(__FILE__).dirname.expand_path / 'dm-adjust'
View
6 dm-adjust/lib/dm-adjust/version.rb
@@ -1,5 +1,7 @@
module DataMapper
- module Adjust
- VERSION = "0.9.3"
+ module More
+ module Adjust
+ VERSION = "0.9.3"
+ end
end
end
View
2 dm-aggregates/Rakefile
@@ -9,7 +9,7 @@ require ROOT + 'lib/dm-aggregates/version'
AUTHOR = "Foy Savas"
EMAIL = "foysavas@gmail.com"
GEM_NAME = "dm-aggregates"
-GEM_VERSION = DataMapper::Aggregates::VERSION
+GEM_VERSION = DataMapper::More::Aggregates::VERSION
GEM_DEPENDENCIES = [["dm-core", GEM_VERSION]]
GEM_CLEAN = ["log", "pkg"]
GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO ] }
View
18 dm-aggregates/lib/dm-aggregates.rb
@@ -1,13 +1,15 @@
require 'rubygems'
-gem 'dm-core', '=0.9.3'
+dir = Pathname(__FILE__).dirname.expand_path + 'dm-aggregates'
+
+require dir + 'version'
+gem 'dm-core', DataMapper::More::Aggregates::VERSION
require 'dm-core'
-dir = Pathname(__FILE__).dirname.expand_path / 'dm-aggregates'
-require dir / 'aggregate_functions'
-require dir / 'model'
-require dir / 'repository'
-require dir / 'collection'
-require dir / 'adapters' / 'data_objects_adapter'
-require dir / 'support' / 'symbol'
+require dir + 'aggregate_functions'
+require dir + 'model'
+require dir + 'repository'
+require dir + 'collection'
+require dir + 'adapters' + 'data_objects_adapter'
+require dir + 'support' + 'symbol'
View
6 dm-aggregates/lib/dm-aggregates/version.rb
@@ -1,5 +1,7 @@
module DataMapper
- module Aggregates
- VERSION = "0.9.3"
+ module More
+ module Aggregates
+ VERSION = "0.9.3"
+ end
end
end
View
2 dm-is-state_machine/TODO
@@ -8,4 +8,4 @@ TODO
* Consider trying out a nested state machine.
* Not real happy with spec/unit/dsl:
- specs are brittle
- - specs don't actually test much
+ - specs don't actually test much
View
9 dm-is-state_machine/lib/dm-is-state_machine/is/data/event.rb
@@ -2,7 +2,7 @@ module DataMapper
module Is
module StateMachine
module Data
-
+
class Event
attr_reader :name, :machine, :transitions
@@ -12,15 +12,14 @@ def initialize(name, machine)
@machine = machine
@transitions = []
end
-
+
def add_transition(from, to)
@transitions << { :from => from, :to => to }
end
-
+
end
-
+
end # Data
end # StateMachine
end # Is
end # DataMapper
-
View
14 dm-is-state_machine/lib/dm-is-state_machine/is/data/machine.rb
@@ -2,20 +2,20 @@ module DataMapper
module Is
module StateMachine
module Data
-
+
# Represents one state machine
class Machine
attr_reader :column, :initial
attr_accessor :current_state_name
attr_accessor :events, :states
-
+
def initialize(column, initial)
@column, @initial = column, initial
@events, @states = [], []
@current_state_name = initial
end
-
+
# Fire (activate) the event with name +event_name+
#
# @api public
@@ -44,7 +44,7 @@ def current_state
find_state(@current_state_name)
# TODO: add caching, i.e. with `@current_state ||= ...`
end
-
+
# Find event whose name is +event_name+
#
# @api semipublic
@@ -52,7 +52,7 @@ def find_event(event_name)
@events.find { |event| event.name.to_s == event_name.to_s }
# TODO: use a data structure that prevents duplicates
end
-
+
# Find state whose name is +event_name+
#
# @api semipublic
@@ -60,9 +60,9 @@ def find_state(state_name)
@states.find { |state| state.name.to_s == state_name.to_s }
# TODO: use a data structure that prevents duplicates
end
-
+
end
-
+
end # Data
end # StateMachine
end # Is
View
6 dm-is-state_machine/lib/dm-is-state_machine/is/data/state.rb
@@ -6,15 +6,15 @@ module Data
class State
attr_reader :name, :machine, :options
-
+
def initialize(name, machine, options = {})
@name = name
@options = options
@machine = machine
end
-
+
end
-
+
end # Data
end # StateMachine
end # Is
View
2 dm-is-state_machine/lib/dm-is-state_machine/is/dsl/event_dsl.rb
@@ -61,7 +61,7 @@ def transitions(options)
end
event_name = @is_state_machine[:event][:name]
event_object = @is_state_machine[:event][:object]
-
+
from = options[:from]
to = options[:to]
event_object.add_transition(from, to)
View
6 dm-is-state_machine/lib/dm-is-state_machine/is/dsl/state_dsl.rb
@@ -15,10 +15,10 @@ module StateDsl
# state :green, :enter => Proc.new { |o| o.log("G") }
# state :yellow, :enter => Proc.new { |o| o.log("Y") }
# state :red, :enter => Proc.new { |o| o.log("R") }
- #
+ #
# # event definitions go here...
# end
- #
+ #
# def log(string)
# Merb::Logger.info(string)
# end
@@ -33,7 +33,7 @@ def state(name, options = {})
state = Data::State.new(name, machine, options)
machine.states << state
end
-
+
end # StateDsl
end # StateMachine
end # Is
View
12 dm-is-state_machine/lib/dm-is-state_machine/is/state_machine.rb
@@ -27,7 +27,7 @@ def is_state_machine(options = {}, &block)
extend DataMapper::Is::StateMachine::EventDsl
extend DataMapper::Is::StateMachine::StateDsl
include DataMapper::Is::StateMachine::InstanceMethods
-
+
# ===== Setup context =====
options = { :column => :state, :initial => nil }.merge(options)
column = options[:column]
@@ -59,9 +59,9 @@ def is_state_machine(options = {}, &block)
# ===== Teardown context =====
pop_state_machine_context
end
-
+
protected
-
+
def push_state_machine_context(label)
((@is_state_machine ||= {})[:context] ||= []) << label
@@ -70,18 +70,18 @@ def push_state_machine_context(label)
# @is_state_machine[:context] ||= []
# @is_state_machine[:context] << label
end
-
+
def pop_state_machine_context
@is_state_machine[:context].pop
end
-
+
def state_machine_context?(label)
(i = @is_state_machine) && (c = i[:context]) &&
c.respond_to?(:include?) && c.include?(label)
end
module InstanceMethods
-
+
def initialize(*args)
super
# ===== Call :enter Proc if present =====
View
2 dm-is-state_machine/lib/dm-is-state_machine/is/version.rb
@@ -4,4 +4,4 @@ module StateMachine
VERSION = "0.9.3"
end
end
-end
+end
View
4 dm-is-state_machine/spec/examples/invalid_events.rb
@@ -1,14 +1,14 @@
# An invalid example.
class InvalidEvents
include DataMapper::Resource
-
+
property :id, Serial
is :state_machine do
state :day
state :night
end
-
+
# The next lines are intentionally incorrect.
#
# 'event' only makes sense in a block under 'is :state_machine'
View
2 dm-is-state_machine/spec/examples/invalid_states.rb
@@ -1,7 +1,7 @@
# An invalid example.
class InvalidStates
include DataMapper::Resource
-
+
property :id, Serial
is :state_machine do
View
6 dm-is-state_machine/spec/examples/invalid_transitions_1.rb
@@ -1,15 +1,15 @@
# An invalid example.
class InvalidTransitions1
include DataMapper::Resource
-
+
property :id, Serial
is :state_machine do
state :happy
state :sad
-
+
event :toggle
-
+
# The next lines are intentionally incorrect.
#
# 'transitions' is only valid when nested beneath 'event'
View
6 dm-is-state_machine/spec/examples/invalid_transitions_2.rb
@@ -1,16 +1,16 @@
# An invalid example.
class InvalidTransitions2
include DataMapper::Resource
-
+
property :id, Serial
is :state_machine do
state :happy
state :sad
-
+
event :toggle
end
-
+
# The next lines are intentionally incorrect.
#
# 'transitions' is only valid when nested beneath 'event'
View
4 dm-is-state_machine/spec/examples/traffic_light.rb
@@ -8,7 +8,7 @@ class TrafficLight
state :green, :enter => Proc.new { |o| o.log << "G" }
state :yellow, :enter => Proc.new { |o| o.log << "Y" }
state :red, :enter => Proc.new { |o| o.log << "R" }
-
+
event :forward do
transitions :from => :green, :to => :yellow
transitions :from => :yellow, :to => :red
@@ -21,7 +21,7 @@ class TrafficLight
transitions :from => :red, :to => :yellow
end
end
-
+
def log; @log ||= [] end
def log=(x); @log ||= [] end
View
22 dm-is-state_machine/spec/integration/traffic_light_spec.rb
@@ -19,31 +19,31 @@
it "should not have a 'state' column" do
@t.attributes.should_not include(:state)
end
-
+
it "should start off in the green state" do
@t.color.should == :green
end
-
+
it "should allow the color to be set" do
@t.color = :yellow
@t.save
@t.color.should == "yellow"
end
-
+
it "should have called the :enter Proc" do
@t.log.should == %w(G)
end
-
+
it "should call the original initialize method" do
@t.init.should == [:init]
end
-
+
describe 'forward!' do
-
+
it "should respond to :forward!" do
@t.respond_to?(:forward!).should == true
end
-
+
it "should transition to :yellow, :red, :green" do
@t.color.should == :green
@t.forward!
@@ -57,7 +57,7 @@
@t.log.should == %w(G Y R G)
@t.new_record?.should == true
end
-
+
it "should skip to :yellow then transition to :red, :green, :yellow" do
@t.color = :yellow
@t.color.should == "yellow"
@@ -89,15 +89,15 @@
@t.log.should == %w(G G Y R)
@t.new_record?.should == true
end
-
+
end
describe 'backward!' do
-
+
it "should respond to 'backward!'" do
@t.respond_to?(:backward!).should == true
end
-
+
it "should transition to :red, :yellow, :green" do
@t.color.should == :green
@t.log.should == %w(G)
View
6 dm-is-state_machine/spec/unit/data/event_spec.rb
@@ -9,18 +9,18 @@ def new_event(*args)
describe DataMapper::Is::StateMachine::Data::Event do
include EventHelper
-
+
before(:each) do
@machine = mock("machine")
@event = new_event(:ping, @machine)
end
-
+
it "#initialize should work" do
@event.name.should == :ping
@event.machine.should == @machine
@event.transitions.should == []
end
-
+
it "#add_transition should work" do
@event.add_transition(:nothing, :pinged)
@event.transitions.should == [{:from => :nothing, :to => :pinged }]
View
10 dm-is-state_machine/spec/unit/data/machine_spec.rb
@@ -5,11 +5,11 @@ module MachineHelper
def new_machine(*args)
DataMapper::Is::StateMachine::Data::Machine.new(*args)
end
-
+
def new_state(name, machine, options = {})
mock(name, :name => name, :machine => machine, :options => options)
end
-
+
def new_event(name, machine)
mock(name, :name => name, :machine => machine)
end
@@ -17,7 +17,7 @@ def new_event(name, machine)
describe DataMapper::Is::StateMachine::Data::Machine do
include MachineHelper
-
+
describe "new Machine, no events" do
before(:each) do
@machine = new_machine(:power, :off)
@@ -82,7 +82,7 @@ def new_event(name, machine)
it "#current_state_name should work" do
@machine.current_state_name.should == :off
end
-
+
it "#find_event should return nothing" do
@machine.find_event(:turn_on).should == @turn_on
end
@@ -93,5 +93,5 @@ def new_event(name, machine)
@machine.current_state_name.should == :on
end
end
-
+
end
View
4 dm-is-state_machine/spec/unit/data/state_spec.rb
@@ -9,12 +9,12 @@ def new_state(*args)
describe DataMapper::Is::StateMachine::Data::State do
include StateHelper
-
+
before(:each) do
@machine = mock("machine")
@state = new_state(:off, @machine)
end
-
+
it "#initialize should work" do
@state.name.should == :off
@state.machine.should == @machine
View
6 dm-is-state_machine/spec/unit/dsl/event_dsl_spec.rb
@@ -2,7 +2,7 @@
require Pathname(__FILE__).dirname.expand_path.parent.parent + 'spec_helper'
describe "EventDsl" do
-
+
describe "event" do
before(:each) do
@@ -23,7 +23,7 @@ class Earth
end
end
-
+
describe "transitions" do
before(:each) do
@@ -52,5 +52,5 @@ class Earth
end
end
-
+
end
View
2 dm-is-state_machine/spec/unit/dsl/state_dsl_spec.rb
@@ -2,7 +2,7 @@
require Pathname(__FILE__).dirname.expand_path.parent.parent + 'spec_helper'
describe "StateDsl" do
-
+
describe "state" do
before(:each) do
View
6 dm-is-state_machine/spec/unit/state_machine_spec.rb
@@ -2,7 +2,7 @@
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
describe "StateMachine" do
-
+
describe "is_state_machine" do
before(:each) do
@@ -18,13 +18,13 @@ class Earth
stub!(:pop_state_machine_context)
end
end
-
+
it "declaration should succeed" do
class Earth
is_state_machine
end
end
-
+
end
end
View
3 dm-types/Manifest.txt
@@ -5,6 +5,7 @@ README.txt
Rakefile
TODO
lib/dm-types.rb
+lib/dm-types/bcrypt_hash.rb
lib/dm-types/csv.rb
lib/dm-types/enum.rb
lib/dm-types/epoch_time.rb
@@ -16,6 +17,7 @@ lib/dm-types/serial.rb
lib/dm-types/uri.rb
lib/dm-types/version.rb
lib/dm-types/yaml.rb
+spec/integration/bcrypt_hash_spec.rb
spec/integration/enum_spec.rb
spec/integration/file_path_spec.rb
spec/integration/flag_spec.rb
@@ -25,6 +27,7 @@ spec/integration/uri_spec.rb
spec/integration/yaml_spec.rb
spec/spec.opts
spec/spec_helper.rb
+spec/unit/bcrypt_hash_spec.rb
spec/unit/csv_spec.rb
spec/unit/enum_spec.rb
spec/unit/epoch_time_spec.rb
View
7 dm-types/lib/dm-types.rb
@@ -16,3 +16,10 @@
require dir / 'uri'
require dir / 'yaml'
require dir / 'serial'
+
+# this looks a little ugly, but everyone who uses dm-types shouldn't have to have ruby-bcrypt installed
+module DataMapper
+ module Types
+ autoload(:BCryptHash, File.join(Pathname(__FILE__).dirname.expand_path, 'dm-types', 'bcrypt_hash'))
+ end
+end
View
31 dm-types/lib/dm-types/bcrypt_hash.rb
@@ -0,0 +1,31 @@
+
+require 'bcrypt'
+
+module DataMapper
+ module Types
+ class BCryptHash < DataMapper::Type
+ primitive String
+ size 60
+
+ def self.load(value, property)
+ if value.nil?
+ nil
+ elsif value.is_a?(String)
+ BCrypt::Password.new(value)
+ else
+ raise ArgumentError.new("+value+ must be nil or a String")
+ end
+ end
+
+ def self.dump(value, property)
+ if value.nil?
+ nil
+ elsif value.is_a?(String)
+ BCrypt::Password.create(value, :cost => BCrypt::Engine::DEFAULT_COST)
+ else
+ raise ArgumentError.new("+value+ must be nil or a String")
+ end
+ end
+ end # class BCryptHash
+ end # module Types
+end # module DataMapper
View
50 dm-types/spec/integration/bcrypt_hash_spec.rb
@@ -0,0 +1,50 @@
+
+require 'pathname'
+require Pathname(__FILE__).dirname.parent.expand_path + 'spec_helper'
+
+begin
+ require 'bcrypt'
+rescue LoadError
+ skip_tests = true
+end
+
+describe "DataMapper::Types::BCryptHash" do
+ unless skip_tests
+ describe "with no options" do
+ before(:each) do
+ class User
+ include DataMapper::Resource
+
+ property :id, Serial
+ property :password, BCryptHash
+ end
+ User.auto_migrate!
+ User.create!(:password => "DataMapper R0cks!")
+ end
+
+ it "should save a password to the DB on creation" do
+ repository(:default) do
+ User.create!(:password => "password1")
+ end
+ user = User.all
+ user[0].password.should == "DataMapper R0cks!"
+ user[1].password.should == "password1"
+ end
+
+ it "should change the password on attribute update" do
+ @user = User.first
+ @user.attribute_set(:password, "D@t@Mapper R0cks!")
+ @user.save
+ @user.password.should_not == "DataMapper R0cks!"
+ @user.password.should == "D@t@Mapper R0cks!"
+ end
+
+ it "should have a cost of BCrypt::Engine::DEFAULT_COST" do
+ @user = User.first
+ @user.password.cost.should == BCrypt::Engine::DEFAULT_COST
+ end
+ end
+ else
+ it "Needs the bcrypt-ruby gem installed"
+ end
+end
View
50 dm-types/spec/unit/bcrypt_hash_spec.rb
@@ -0,0 +1,50 @@
+require 'pathname'
+require Pathname(__FILE__).dirname.parent.expand_path + 'spec_helper'
+
+include DataMapper::Types
+
+begin
+ require 'bcrypt'
+rescue LoadError
+ skip_tests = true
+end
+
+describe "DataMapper::Types::BCryptHash" do
+ unless skip_tests
+
+ before(:each) do
+ @clear_password = "DataMapper R0cks!"
+ @crypted_password = BCrypt::Password.create(@clear_password)
+ end
+
+ describe ".dump" do
+ it "should return a crypted hash as a BCrypt::Password" do
+ BCryptHash.dump(@clear_password, :property).should be_an_instance_of(BCrypt::Password)
+ end
+
+ it "should return a string that is 60 characters long" do
+ BCryptHash.dump(@clear_password, :property).should have(60).characters
+ end
+
+ it "should return nil if nil is passed" do
+ BCryptHash.dump(nil, :property).should be_nil
+ end
+ end
+
+ describe ".load" do
+ it "should return the password as a BCrypt::Password" do
+ BCryptHash.load(@crypted_password, :property).should be_an_instance_of(BCrypt::Password)
+ end
+
+ it "should return the password as a password which matches" do
+ BCryptHash.load(@crypted_password, :property).should == @clear_password
+ end
+
+ it "should return nil if given nil" do
+ FilePath.load(nil, :property).should be_nil
+ end
+ end
+ else
+ it "requires the bcrypt-ruby gem to test"
+ end
+end
View
62 dm-validations/lib/dm-validations/auto_validate.rb
@@ -1,6 +1,29 @@
module DataMapper
+ class Property
+ # for options_with_message
+ PROPERTY_OPTIONS << :message << :messages
+ end
+
module Validate
module AutoValidate
+ # adds message for validator
+ def options_with_message(base_options, property, validator_name)
+ options = base_options.clone
+ opts = property.options
+ options[:message] = if opts[:messages]
+ if opts[:messages].is_a?(Hash) and msg = opts[:messages][validator_name]
+ msg
+ else
+ nil
+ end
+ elsif opts[:message]
+ opts[:message]
+ else
+ nil
+ end
+ options
+ end
+
##
# Auto-generate validations for a given property. This will only occur
@@ -33,6 +56,21 @@ module AutoValidate
# Using a Integer type causes a validates_is_number
# validator to be created for the property. integer_only
# is set to false, and precision/scale match the property
+ #
+ #
+ # Messages
+ #
+ # :messages => {..}
+ # Setting :messages hash replaces standard error messages
+ # with custom ones. For instance:
+ # :messages => {:presence => "Field is required",
+ # :format => "Field has invalid format"}
+ # Hash keys are: :presence, :format, :length, :is_unique,
+ # :is_number, :is_primitive
+ #
+ # :message => "Some message"
+ # It is just shortcut if only one validation option is set
+ #
def auto_generate_validations(property)
property.options[:auto_validation] = true unless property.options.has_key?(:auto_validation)
return unless property.options[:auto_validation]
@@ -44,7 +82,8 @@ def auto_generate_validations(property)
# presence
unless opts[:allow_nil]
- validates_present property.name, opts
+ # validates_present property.name, opts
+ validates_present property.name, options_with_message(opts, property, :presence)
end
# length
@@ -56,39 +95,46 @@ def auto_generate_validations(property)
else
opts[:maximum] = len
end
- validates_length property.name, opts
+ # validates_length property.name, opts
+ validates_length property.name, options_with_message(opts, property, :length)
end
# format
if property.options.has_key?(:format)
opts[:with] = property.options[:format]
- validates_format property.name, opts
+ # validates_format property.name, opts
+ validates_format property.name, options_with_message(opts, property, :format)
end
# uniqueness validator
if property.options.has_key?(:unique)
value = property.options[:unique]
if value.is_a?(Array) || value.is_a?(Symbol)
- validates_is_unique property.name, :scope => Array(value)
+ # validates_is_unique property.name, :scope => Array(value)
+ validates_is_unique property.name, options_with_message({:scope => Array(value)}, property, :is_unique)
elsif value.is_a?(TrueClass)
- validates_is_unique property.name
+ # validates_is_unique property.name
+ validates_is_unique property.name, options_with_message({}, property, :is_unique)
end
end
# numeric validator
if Integer == property.type
opts[:integer_only] = true
- validates_is_number property.name, opts
+ # validates_is_number property.name, opts
+ validates_is_number property.name, options_with_message(opts, property, :is_number)
elsif BigDecimal == property.type || Float == property.type
opts[:precision] = property.precision
opts[:scale] = property.scale
- validates_is_number property.name, opts
+ # validates_is_number property.name, opts
+ validates_is_number property.name, options_with_message(opts, property, :is_number)
else
# We only need this in the case we don't already
# have a numeric validator, because otherwise
# it will cause duplicate validation errors
unless property.custom?
- validates_is_primitive property.name, opts
+ # validates_is_primitive property.name, opts
+ validates_is_primitive property.name, options_with_message(opts, property, :is_primitive)
end
end
end
View
49 dm-validations/spec/integration/auto_validate_spec.rb
@@ -259,4 +259,53 @@ class HasNotNullableParanoidBoolean
end
end
end
+
+ describe 'for custom messages' do
+ it "should have correct error message" do
+ custom_boat = Class.new do
+ include DataMapper::Resource
+ property :id, Integer, :serial => true
+ property :name, String, :nullable => false, :message => "This boat must have name"
+ end
+ boat = custom_boat.new
+ boat.should_not be_valid
+
+ boat.errors.on(:name).should eql(["This boat must have name"])
+ end
+
+ it "should have correct error messages" do
+ custom_boat = Class.new do
+ include DataMapper::Resource
+ property :id, Integer, :serial => true
+ property :name, String, :nullable => false, :length => 5..20, :format => /^[a-z]+$/,
+ :messages => {
+ :presence => "This boat must have name",
+ :length => "Name must have at least 4 and at most 20 chars",
+ :format => "Please use only small letters"
+ }
+ end
+
+ boat = custom_boat.new
+ boat.should_not be_valid
+ boat.errors.on(:name).should include("This boat must have name")
+ boat.errors.on(:name).should include("Name must have at least 4 and at most 20 chars")
+ boat.errors.on(:name).should include("Please use only small letters")
+
+ boat.name = "%%"
+ boat.should_not be_valid
+ boat.errors.on(:name).should_not include("This boat must have name")
+ boat.errors.on(:name).should include("Name must have at least 4 and at most 20 chars")
+ boat.errors.on(:name).should include("Please use only small letters")
+
+ boat.name = "%%asd"
+ boat.should_not be_valid
+ boat.errors.on(:name).should_not include("This boat must have name")
+ boat.errors.on(:name).should_not include("Name must have at least 4 and at most 20 chars")
+ boat.errors.on(:name).should include("Please use only small letters")
+
+ boat.name = "superboat"
+ boat.should be_valid
+ boat.errors.on(:name).should be_nil
+ end
+ end
end
View
3 merb_datamapper/lib/merb_datamapper.rb
@@ -1,7 +1,8 @@
if defined?(Merb::Plugins)
require 'rubygems'
+ require 'merb_datamapper/version'
- gem 'dm-core', '=0.9.3'
+ gem 'dm-core', DataMapper::MerbDataMapper::VERSION
require 'dm-core'
if File.file?(Merb.dir_for(:config) / "database.yml")
View
6 merb_datamapper/lib/merb_datamapper/merbtasks.rb
@@ -8,6 +8,12 @@
end
namespace :db do
+ desc "Create a sample database.yml file"
+ task :database_yaml => :merb_start do
+ sample_location = File.join(File.dirname(__FILE__), "..", "merb", "orms", "data_mapper", "database.yml.sample")
+ target_location = Merb.dir_for(:config)
+ FileUtils.cp sample_location, target_location
+ end
desc "Perform automigration"
task :automigrate => :merb_start do
::DataMapper::AutoMigrator.auto_migrate

0 comments on commit 7d58992

Please sign in to comment.
Something went wrong with that request. Please try again.