aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
authorCarl Lerche <carllerche@mac.com>2009-09-01 12:19:09 -0700
committerCarl Lerche <carllerche@mac.com>2009-09-01 12:19:09 -0700
commit016b1d3596ce12367edac8bb442f5c630a453ecf (patch)
tree49435918ebb372f617c3cc95bc495f6dd5c12d24 /activemodel
parent22d5e3d89d619acb9179dfcdd33f1afaee9567ca (diff)
parentda636809daca9c338200811d3590e446f57c8e81 (diff)
downloadrails-016b1d3596ce12367edac8bb442f5c630a453ecf.tar.gz
rails-016b1d3596ce12367edac8bb442f5c630a453ecf.tar.bz2
rails-016b1d3596ce12367edac8bb442f5c630a453ecf.zip
Merge branch 'master' of git@github.com:rails/rails
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/MIT-LICENSE21
-rwxr-xr-xactivemodel/Rakefile52
-rw-r--r--activemodel/activemodel.gemspec31
-rw-r--r--activemodel/lib/active_model.rb1
-rw-r--r--activemodel/lib/active_model/dirty.rb14
-rw-r--r--activemodel/lib/active_model/validations/numericality.rb21
-rw-r--r--activemodel/lib/active_model/version.rb9
-rw-r--r--activemodel/test/cases/validations/numericality_validation_test.rb18
8 files changed, 163 insertions, 4 deletions
diff --git a/activemodel/MIT-LICENSE b/activemodel/MIT-LICENSE
new file mode 100644
index 0000000000..e7accc5ea1
--- /dev/null
+++ b/activemodel/MIT-LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2004-2009 David Heinemeier Hansson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/activemodel/Rakefile b/activemodel/Rakefile
index ae2fbdb002..dcd1eaa444 100755
--- a/activemodel/Rakefile
+++ b/activemodel/Rakefile
@@ -1,7 +1,13 @@
-#!/usr/bin/env ruby
-require 'rake'
+require File.join(File.dirname(__FILE__), 'lib', 'active_model', 'version')
+
+PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
+PKG_NAME = 'activemodel'
+PKG_VERSION = ActiveModel::VERSION::STRING + PKG_BUILD
+PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
+RELEASE_NAME = "REL #{PKG_VERSION}"
+
+
require 'rake/testtask'
-require 'rake/rdoctask'
task :default => :test
@@ -10,6 +16,7 @@ Rake::TestTask.new do |t|
t.test_files = Dir.glob("test/cases/**/*_test.rb").sort
t.verbose = true
end
+
task :isolated_test do
ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
Dir.glob("test/**/*_test.rb").all? do |file|
@@ -17,6 +24,9 @@ task :isolated_test do
end or raise "Failures"
end
+
+require 'rake/rdoctask'
+
# Generate the RDoc documentation
Rake::RDocTask.new do |rdoc|
rdoc.rdoc_dir = 'doc'
@@ -27,3 +37,39 @@ Rake::RDocTask.new do |rdoc|
rdoc.rdoc_files.include('README', 'CHANGES')
rdoc.rdoc_files.include('lib/**/*.rb')
end
+
+
+require 'rake/packagetask'
+require 'rake/gempackagetask'
+
+spec = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = PKG_NAME
+ s.version = PKG_VERSION
+ s.summary = "A toolkit for building other modeling frameworks like ActiveRecord"
+ s.description = %q{Extracts common modeling concerns from ActiveRecord to share between similar frameworks like ActiveResource.}
+
+ s.author = "David Heinemeier Hansson"
+ s.email = "david@loudthinking.com"
+ s.rubyforge_project = "activemodel"
+ s.homepage = "http://www.rubyonrails.org"
+
+ s.has_rdoc = true
+
+ s.add_dependency('activesupport', '= 3.0.pre' + PKG_BUILD)
+
+ s.require_path = 'lib'
+ s.files = Dir["CHANGELOG", "MIT-LICENSE", "README", "Rakefile", "lib/**/*", "test/**/*"]
+end
+
+Rake::GemPackageTask.new(spec) do |p|
+ p.gem_spec = spec
+ p.need_tar = true
+ p.need_zip = true
+end
+
+task :gemspec do
+ File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file|
+ file.puts spec.to_ruby
+ end
+end \ No newline at end of file
diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec
new file mode 100644
index 0000000000..700b645eb3
--- /dev/null
+++ b/activemodel/activemodel.gemspec
@@ -0,0 +1,31 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{activemodel}
+ s.version = "3.0.pre"
+
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
+ s.authors = ["David Heinemeier Hansson"]
+ s.date = %q{2009-08-31}
+ s.description = %q{Extracts common modeling concerns from ActiveRecord to share between similar frameworks like ActiveResource.}
+ s.email = %q{david@loudthinking.com}
+ s.files = ["CHANGELOG", "MIT-LICENSE", "README", "Rakefile", "lib/active_model", "lib/active_model/attribute_methods.rb", "lib/active_model/conversion.rb", "lib/active_model/deprecated_error_methods.rb", "lib/active_model/dirty.rb", "lib/active_model/errors.rb", "lib/active_model/lint.rb", "lib/active_model/locale", "lib/active_model/locale/en.yml", "lib/active_model/naming.rb", "lib/active_model/observing.rb", "lib/active_model/serialization.rb", "lib/active_model/serializers", "lib/active_model/serializers/json.rb", "lib/active_model/serializers/xml.rb", "lib/active_model/state_machine", "lib/active_model/state_machine/event.rb", "lib/active_model/state_machine/machine.rb", "lib/active_model/state_machine/state.rb", "lib/active_model/state_machine/state_transition.rb", "lib/active_model/state_machine.rb", "lib/active_model/test_case.rb", "lib/active_model/validations", "lib/active_model/validations/acceptance.rb", "lib/active_model/validations/confirmation.rb", "lib/active_model/validations/exclusion.rb", "lib/active_model/validations/format.rb", "lib/active_model/validations/inclusion.rb", "lib/active_model/validations/length.rb", "lib/active_model/validations/numericality.rb", "lib/active_model/validations/presence.rb", "lib/active_model/validations/with.rb", "lib/active_model/validations.rb", "lib/active_model/validations_repair_helper.rb", "lib/active_model/version.rb", "lib/active_model.rb", "lib/activemodel.rb", "test/cases", "test/cases/helper.rb", "test/cases/lint_test.rb", "test/cases/naming_test.rb", "test/cases/observing_test.rb", "test/cases/serializeration", "test/cases/serializeration/json_serialization_test.rb", "test/cases/serializeration/xml_serialization_test.rb", "test/cases/state_machine", "test/cases/state_machine/event_test.rb", "test/cases/state_machine/machine_test.rb", "test/cases/state_machine/state_test.rb", "test/cases/state_machine/state_transition_test.rb", "test/cases/state_machine_test.rb", "test/cases/tests_database.rb", "test/cases/validations", "test/cases/validations/acceptance_validation_test.rb", "test/cases/validations/conditional_validation_test.rb", "test/cases/validations/confirmation_validation_test.rb", "test/cases/validations/exclusion_validation_test.rb", "test/cases/validations/format_validation_test.rb", "test/cases/validations/i18n_generate_message_validation_test.rb", "test/cases/validations/i18n_validation_test.rb", "test/cases/validations/inclusion_validation_test.rb", "test/cases/validations/length_validation_test.rb", "test/cases/validations/numericality_validation_test.rb", "test/cases/validations/presence_validation_test.rb", "test/cases/validations/with_validation_test.rb", "test/cases/validations_test.rb", "test/config.rb", "test/fixtures", "test/fixtures/topics.yml", "test/models", "test/models/contact.rb", "test/models/custom_reader.rb", "test/models/developer.rb", "test/models/person.rb", "test/models/reply.rb", "test/models/topic.rb", "test/schema.rb"]
+ s.homepage = %q{http://www.rubyonrails.org}
+ s.require_paths = ["lib"]
+ s.rubyforge_project = %q{activemodel}
+ s.rubygems_version = %q{1.3.5}
+ s.summary = %q{A toolkit for building other modeling frameworks like ActiveRecord}
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ s.add_runtime_dependency(%q<activesupport>, ["= 3.0.pre"])
+ else
+ s.add_dependency(%q<activesupport>, ["= 3.0.pre"])
+ end
+ else
+ s.add_dependency(%q<activesupport>, ["= 3.0.pre"])
+ end
+end
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index 5bb931be7f..67f529262d 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -41,6 +41,7 @@ module ActiveModel
autoload :TestCase, 'active_model/test_case'
autoload :Validations, 'active_model/validations'
autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper'
+ autoload :VERSION, 'active_model/version'
module Serializers
autoload :JSON, 'active_model/serializers/json'
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index 624c3647ca..735c61df74 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -72,12 +72,26 @@ module ActiveModel
changed.inject({}) { |h, attr| h[attr] = attribute_change(attr); h }
end
+ # Map of attributes that were changed when the model was saved.
+ # person.name # => 'bob'
+ # person.name = 'robert'
+ # person.save
+ # person.previous_changes # => {'name' => ['bob, 'robert']}
+ def previous_changes
+ previously_changed_attributes
+ end
+
private
# Map of change <tt>attr => original value</tt>.
def changed_attributes
@changed_attributes ||= {}
end
+ # Map of fields that were changed when the model was saved
+ def previously_changed_attributes
+ @previously_changed || {}
+ end
+
# Handle <tt>*_changed?</tt> for +method_missing+.
def attribute_changed?(attr)
changed_attributes.include?(attr)
diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb
index ada6e28594..32dbcd82d0 100644
--- a/activemodel/lib/active_model/validations/numericality.rb
+++ b/activemodel/lib/active_model/validations/numericality.rb
@@ -31,6 +31,21 @@ module ActiveModel
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value.
+ #
+ # The following checks can also be supplied with a proc or a symbol which corresponds to a method:
+ # * <tt>:greater_than</tt>
+ # * <tt>:greater_than_or_equal_to</tt>
+ # * <tt>:equal_to</tt>
+ # * <tt>:less_than</tt>
+ # * <tt>:less_than_or_equal_to</tt>
+ #
+ # class Person < ActiveRecord::Base
+ # validates_numericality_of :width, :less_than => Proc.new { |person| person.height }
+ # validates_numericality_of :width, :greater_than => :minimum_weight
+ # end
+ #
+ #
+
def validates_numericality_of(*attr_names)
configuration = { :only_integer => false, :allow_nil => false }
configuration.update(attr_names.extract_options!)
@@ -38,7 +53,8 @@ module ActiveModel
numericality_options = ALL_NUMERICALITY_CHECKS.keys & configuration.keys
(numericality_options - [ :odd, :even ]).each do |option|
- raise ArgumentError, ":#{option} must be a number" unless configuration[option].is_a?(Numeric)
+ value = configuration[option]
+ raise ArgumentError, ":#{option} must be a number, a symbol or a proc" unless value.is_a?(Numeric) || value.is_a?(Proc) || value.is_a?(Symbol)
end
validates_each(attr_names,configuration) do |record, attr_name, value|
@@ -74,6 +90,9 @@ module ActiveModel
record.errors.add(attr_name, option, :value => raw_value, :default => configuration[:message])
end
else
+ configuration[option] = configuration[option].call(record) if configuration[option].is_a? Proc
+ configuration[option] = record.method(configuration[option]).call if configuration[option].is_a? Symbol
+
unless raw_value.method(ALL_NUMERICALITY_CHECKS[option])[configuration[option]]
record.errors.add(attr_name, option, :default => configuration[:message], :value => raw_value, :count => configuration[option])
end
diff --git a/activemodel/lib/active_model/version.rb b/activemodel/lib/active_model/version.rb
new file mode 100644
index 0000000000..0c233b7b4f
--- /dev/null
+++ b/activemodel/lib/active_model/version.rb
@@ -0,0 +1,9 @@
+module ActiveModel
+ module VERSION #:nodoc:
+ MAJOR = 3
+ MINOR = 0
+ TINY = "pre"
+
+ STRING = [MAJOR, MINOR, TINY].join('.')
+ end
+end
diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb
index 0af6eb69ce..d3201966dc 100644
--- a/activemodel/test/cases/validations/numericality_validation_test.rb
+++ b/activemodel/test/cases/validations/numericality_validation_test.rb
@@ -106,6 +106,24 @@ class NumericalityValidationTest < ActiveModel::TestCase
valid!([2])
end
+ def test_validates_numericality_with_proc
+ Topic.send(:define_method, :min_approved, lambda { 5 })
+ Topic.validates_numericality_of :approved, :greater_than_or_equal_to => Proc.new {|topic| topic.min_approved }
+
+ invalid!([3, 4])
+ valid!([5, 6])
+ Topic.send(:remove_method, :min_approved)
+ end
+
+ def test_validates_numericality_with_symbol
+ Topic.send(:define_method, :max_approved, lambda { 5 })
+ Topic.validates_numericality_of :approved, :less_than_or_equal_to => :max_approved
+
+ invalid!([6])
+ valid!([4, 5])
+ Topic.send(:remove_method, :max_approved)
+ end
+
def test_validates_numericality_with_numeric_message
Topic.validates_numericality_of :approved, :less_than => 4, :message => "smaller than {{count}}"
topic = Topic.new("title" => "numeric test", "approved" => 10)