aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
authorEmilio Tagua <miloops@gmail.com>2009-06-23 18:13:46 -0300
committerEmilio Tagua <miloops@gmail.com>2009-06-23 18:13:46 -0300
commitb9088dce07f8525cdb84a1312a77b81db79067d6 (patch)
tree72ace069842b074981ba814ef1c335271176ce27 /activemodel
parent4864f92ee34e840307d968fa8b04972b6d786fe8 (diff)
parent4417a19b035d73eb46a5e06e296a4b1c8091bef1 (diff)
downloadrails-b9088dce07f8525cdb84a1312a77b81db79067d6.tar.gz
rails-b9088dce07f8525cdb84a1312a77b81db79067d6.tar.bz2
rails-b9088dce07f8525cdb84a1312a77b81db79067d6.zip
Merge commit 'rails/master'
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/lib/active_model.rb7
-rw-r--r--activemodel/lib/active_model/attributes.rb17
-rw-r--r--activemodel/lib/active_model/errors.rb6
-rw-r--r--activemodel/lib/active_model/naming.rb25
-rw-r--r--activemodel/lib/active_model/serializers/json.rb38
-rw-r--r--activemodel/lib/active_model/validations.rb6
-rw-r--r--activemodel/test/cases/attributes_test.rb30
-rw-r--r--activemodel/test/cases/json_serialization_test.rb64
-rw-r--r--activemodel/test/cases/naming_test.rb27
-rw-r--r--activemodel/test/cases/validations/presence_validation_test.rb18
10 files changed, 221 insertions, 17 deletions
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index 73cee9b88f..544121c593 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -26,15 +26,22 @@ $:.unshift(activesupport_path) if File.directory?(activesupport_path)
require 'active_support'
module ActiveModel
+ autoload :Attributes, 'active_model/attributes'
autoload :Base, 'active_model/base'
autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods'
autoload :Errors, 'active_model/errors'
+ autoload :Name, 'active_model/naming'
+ autoload :Naming, 'active_model/naming'
autoload :Observer, 'active_model/observing'
autoload :Observing, 'active_model/observing'
autoload :StateMachine, 'active_model/state_machine'
autoload :TestCase, 'active_model/test_case'
autoload :Validations, 'active_model/validations'
autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper'
+
+ module Serializers
+ autoload :JSON, 'active_model/serializers/json'
+ end
end
I18n.load_path << File.dirname(__FILE__) + '/active_model/locale/en.yml'
diff --git a/activemodel/lib/active_model/attributes.rb b/activemodel/lib/active_model/attributes.rb
new file mode 100644
index 0000000000..4665525281
--- /dev/null
+++ b/activemodel/lib/active_model/attributes.rb
@@ -0,0 +1,17 @@
+require 'active_support/core_ext/object/instance_variables'
+
+module ActiveModel
+ module Attributes
+ def attributes
+ instance_values
+ end
+
+ def read_attribute(attr_name)
+ instance_variable_get(:"@#{attr_name}")
+ end
+
+ def write_attribute(attr_name, value)
+ instance_variable_set(:"@#{attr_name}", value)
+ end
+ end
+end
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 2e643f108f..a4cf700231 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -68,7 +68,7 @@ module ActiveModel
# Will add an error message to each of the attributes in +attributes+ that is empty.
def add_on_empty(attributes, custom_message = nil)
[attributes].flatten.each do |attribute|
- value = @base.get_attribute_value(attribute)
+ value = @base.send(attribute)
is_empty = value.respond_to?(:empty?) ? value.empty? : false
add(attribute, :empty, :default => custom_message) unless !value.nil? && !is_empty
end
@@ -77,7 +77,7 @@ module ActiveModel
# Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?).
def add_on_blank(attributes, custom_message = nil)
[attributes].flatten.each do |attribute|
- value = @base.get_attribute_value(attribute)
+ value = @base.send(attribute)
add(attribute, :blank, :default => custom_message) if value.blank?
end
end
@@ -146,7 +146,7 @@ module ActiveModel
defaults = defaults.compact.flatten << :"messages.#{message}"
key = defaults.shift
- value = @base.get_attribute_value(attribute)
+ value = @base.send(attribute)
options = { :default => defaults,
:model => @base.class.name.humanize,
diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb
new file mode 100644
index 0000000000..ffb44e3824
--- /dev/null
+++ b/activemodel/lib/active_model/naming.rb
@@ -0,0 +1,25 @@
+require 'active_support/inflector'
+
+module ActiveModel
+ class Name < String
+ attr_reader :singular, :plural, :element, :collection, :partial_path
+ alias_method :cache_key, :collection
+
+ def initialize(name)
+ super
+ @singular = ActiveSupport::Inflector.underscore(self).tr('/', '_').freeze
+ @plural = ActiveSupport::Inflector.pluralize(@singular).freeze
+ @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze
+ @collection = ActiveSupport::Inflector.tableize(self).freeze
+ @partial_path = "#{@collection}/#{@element}".freeze
+ end
+ end
+
+ module Naming
+ # Returns an ActiveModel::Name object for module. It can be
+ # used to retrieve all kinds of naming-related information.
+ def model_name
+ @_model_name ||= ActiveModel::Name.new(name)
+ end
+ end
+end
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
new file mode 100644
index 0000000000..60b5cbe948
--- /dev/null
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -0,0 +1,38 @@
+require 'active_support/json'
+require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/core_ext/hash/except'
+require 'active_support/core_ext/hash/slice'
+
+module ActiveModel
+ module Serializers
+ module JSON
+ extend ActiveSupport::Concern
+ include ActiveModel::Attributes
+
+ included do
+ cattr_accessor :include_root_in_json, :instance_writer => false
+ end
+
+ def encode_json(encoder)
+ options = encoder.options || {}
+
+ hash = if options[:only]
+ only = Array.wrap(options[:only]).map { |attr| attr.to_s }
+ attributes.slice(*only)
+ elsif options[:except]
+ except = Array.wrap(options[:except]).map { |attr| attr.to_s }
+ attributes.except(*except)
+ else
+ attributes
+ end
+
+ hash = { self.class.model_name.element => hash } if include_root_in_json
+ ActiveSupport::JSON.encode(hash)
+ end
+
+ def as_json(options = nil)
+ self
+ end
+ end
+ end
+end
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 6b6f51d942..5223cea135 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -64,7 +64,7 @@ module ActiveModel
# Declare the validation.
send(validation_method(options[:on]), options) do |record|
attrs.each do |attr|
- value = record.get_attribute_value(attr)
+ value = record.send(attr)
next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
yield record, attr, value
end
@@ -93,10 +93,6 @@ module ActiveModel
def invalid?
!valid?
end
-
- def get_attribute_value(attribute)
- respond_to?(attribute.to_sym) ? send(attribute.to_sym) : instance_variable_get(:"@#{attribute}")
- end
end
end
diff --git a/activemodel/test/cases/attributes_test.rb b/activemodel/test/cases/attributes_test.rb
new file mode 100644
index 0000000000..5f3ea839a4
--- /dev/null
+++ b/activemodel/test/cases/attributes_test.rb
@@ -0,0 +1,30 @@
+require 'cases/helper'
+
+class AttributesTest < ActiveModel::TestCase
+ class Person
+ include ActiveModel::Attributes
+ attr_accessor :name
+ end
+
+ test "reads attribute" do
+ p = Person.new
+ assert_equal nil, p.read_attribute(:name)
+
+ p.name = "Josh"
+ assert_equal "Josh", p.read_attribute(:name)
+ end
+
+ test "writes attribute" do
+ p = Person.new
+ assert_equal nil, p.name
+
+ p.write_attribute(:name, "Josh")
+ assert_equal "Josh", p.name
+ end
+
+ test "returns all attributes" do
+ p = Person.new
+ p.name = "Josh"
+ assert_equal({"name" => "Josh"}, p.attributes)
+ end
+end
diff --git a/activemodel/test/cases/json_serialization_test.rb b/activemodel/test/cases/json_serialization_test.rb
new file mode 100644
index 0000000000..abcec67a85
--- /dev/null
+++ b/activemodel/test/cases/json_serialization_test.rb
@@ -0,0 +1,64 @@
+require 'cases/helper'
+
+class JsonSerializationTest < ActiveModel::TestCase
+ class Contact
+ extend ActiveModel::Naming
+ include ActiveModel::Serializers::JSON
+ attr_accessor :name, :age, :created_at, :awesome, :preferences
+ end
+
+ def setup
+ @contact = Contact.new
+ @contact.name = 'Konata Izumi'
+ @contact.age = 16
+ @contact.created_at = Time.utc(2006, 8, 1)
+ @contact.awesome = true
+ @contact.preferences = { 'shows' => 'anime' }
+ end
+
+ test "should include root in json" do
+ begin
+ Contact.include_root_in_json = true
+ json = @contact.to_json
+
+ assert_match %r{^\{"contact":\{}, json
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"awesome":true}, json
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
+ ensure
+ Contact.include_root_in_json = false
+ end
+ end
+
+ test "should encode all encodable attributes" do
+ json = @contact.to_json
+
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"awesome":true}, json
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
+ end
+
+ test "should allow attribute filtering with only" do
+ json = @contact.to_json(:only => [:name, :age])
+
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert_no_match %r{"awesome":true}, json
+ assert !json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_no_match %r{"preferences":\{"shows":"anime"\}}, json
+ end
+
+ test "should allow attribute filtering with except" do
+ json = @contact.to_json(:except => [:name, :age])
+
+ assert_no_match %r{"name":"Konata Izumi"}, json
+ assert_no_match %r{"age":16}, json
+ assert_match %r{"awesome":true}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
+ end
+end
diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb
new file mode 100644
index 0000000000..e75d4541a3
--- /dev/null
+++ b/activemodel/test/cases/naming_test.rb
@@ -0,0 +1,27 @@
+require 'cases/helper'
+
+class NamingTest < Test::Unit::TestCase
+ def setup
+ @model_name = ActiveModel::Name.new('Post::TrackBack')
+ end
+
+ def test_singular
+ assert_equal 'post_track_back', @model_name.singular
+ end
+
+ def test_plural
+ assert_equal 'post_track_backs', @model_name.plural
+ end
+
+ def test_element
+ assert_equal 'track_back', @model_name.element
+ end
+
+ def test_collection
+ assert_equal 'post/track_backs', @model_name.collection
+ end
+
+ def test_partial_path
+ assert_equal 'post/track_backs/track_back', @model_name.partial_path
+ end
+end
diff --git a/activemodel/test/cases/validations/presence_validation_test.rb b/activemodel/test/cases/validations/presence_validation_test.rb
index f6bed4903a..aa5bdf1e62 100644
--- a/activemodel/test/cases/validations/presence_validation_test.rb
+++ b/activemodel/test/cases/validations/presence_validation_test.rb
@@ -31,15 +31,15 @@ class PresenceValidationTest < ActiveModel::TestCase
assert t.save
end
- def test_validates_presence_of_with_custom_message_using_quotes
- repair_validations(Developer) do
- Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes"
- d = Developer.new
- d.name = "Joe"
- assert !d.valid?
- assert_equal ["This string contains 'single' and \"double\" quotes"], d.errors[:non_existent]
- end
- end
+ # def test_validates_presence_of_with_custom_message_using_quotes
+ # repair_validations(Developer) do
+ # Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes"
+ # d = Developer.new
+ # d.name = "Joe"
+ # assert !d.valid?
+ # assert_equal ["This string contains 'single' and \"double\" quotes"], d.errors[:non_existent]
+ # end
+ # end
def test_validates_presence_of_for_ruby_class
repair_validations(Person) do