aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb1
-rw-r--r--actionpack/lib/action_view/helpers/active_record_helper.rb24
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb13
-rw-r--r--actionpack/test/abstract_unit.rb1
-rw-r--r--actionpack/test/activerecord/render_partial_with_record_identification_test.rb2
-rw-r--r--actionpack/test/controller/record_identifier_test.rb2
-rw-r--r--actionpack/test/controller/redirect_test.rb2
-rw-r--r--actionpack/test/lib/controller/fake_models.rb4
-rw-r--r--actionpack/test/template/active_record_helper_test.rb16
-rw-r--r--actionpack/test/template/atom_feed_helper_test.rb9
-rw-r--r--actionpack/test/template/prototype_helper_test.rb8
-rw-r--r--actionpack/test/template/record_tag_helper_test.rb2
-rw-r--r--actionpack/test/template/test_test.rb2
-rw-r--r--actionpack/test/template/url_helper_test.rb4
-rw-r--r--activemodel/lib/active_model.rb1
-rw-r--r--activemodel/lib/active_model/api_compliant.rb25
-rwxr-xr-xactiverecord/lib/active_record/base.rb7
17 files changed, 91 insertions, 32 deletions
diff --git a/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb
index c6f7de17bd..159d869a54 100644
--- a/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb
+++ b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb
@@ -77,6 +77,7 @@ module ActionController
end
record = extract_record(record_or_hash_or_array)
+ record = record.to_model if record.respond_to?(:to_model)
namespace = extract_namespace(record_or_hash_or_array)
args = case record_or_hash_or_array
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index 75cc651968..8dffd3bc91 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -77,6 +77,7 @@ module ActionView
# * <tt>:submit_value</tt> - The text of the submit button (default: "Create" if a new record, otherwise "Update").
def form(record_name, options = {})
record = instance_variable_get("@#{record_name}")
+ record = record.to_model if record.respond_to?(:to_model)
options = options.symbolize_keys
options[:action] ||= record.new_record? ? "create" : "update"
@@ -121,6 +122,8 @@ module ActionView
end
options.reverse_merge!(:prepend_text => '', :append_text => '', :css_class => 'formError')
+ object = object.to_model if object.respond_to?(:to_model)
+
if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) &&
(errors = obj.errors[method])
content_tag("div",
@@ -179,6 +182,8 @@ module ActionView
objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
end
+ objects.map! {|o| o.respond_to?(:to_model) ? o.to_model : o }
+
count = objects.inject(0) {|sum, object| sum + object.errors.count }
unless count.zero?
html = {}
@@ -226,7 +231,14 @@ module ActionView
end
end
- class InstanceTag #:nodoc:
+ module ActiveRecordInstanceTag
+ def object
+ @active_model_object ||= begin
+ object = super
+ object.respond_to?(:to_model) ? object.to_model : object
+ end
+ end
+
def to_tag(options = {})
case column_type
when :string
@@ -248,11 +260,9 @@ module ActionView
end
%w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth|
- without = "#{meth}_without_error_wrapping"
- define_method "#{meth}_with_error_wrapping" do |*args|
- error_wrapping(send(without, *args))
+ define_method meth do |*|
+ error_wrapping(super)
end
- alias_method_chain meth, :error_wrapping
end
def error_wrapping(html_tag)
@@ -267,5 +277,9 @@ module ActionView
object.send(:column_for_attribute, @method_name).type
end
end
+
+ class InstanceTag
+ include ActiveRecordInstanceTag
+ end
end
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index a74709e98a..ecbdcd8e7a 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -626,8 +626,8 @@ module ActionView
# Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object
# assigned to the template (identified by +object+). This object must be an instance object (@object) and not a local object.
- # It's intended that +method+ returns an integer and if that integer is above zero, then the checkbox is checked.
- # Additional options on the input tag can be passed as a hash with +options+. The +checked_value+ defaults to 1
+ # It's intended that +method+ returns an integer and if that integer is above zero, then the checkbox is checked.
+ # Additional options on the input tag can be passed as a hash with +options+. The +checked_value+ defaults to 1
# while the default +unchecked_value+ is set to 0 which is convenient for boolean values.
#
# ==== Gotcha
@@ -709,7 +709,8 @@ module ActionView
end
end
- class InstanceTag #:nodoc:
+ module InstanceTagMethods #:nodoc:
+ extend ActiveSupport::Concern
include Helpers::TagHelper, Helpers::FormTagHelper
attr_reader :method_name, :object_name
@@ -832,7 +833,7 @@ module ActionView
self.class.value_before_type_cast(object, @method_name)
end
- class << self
+ module ClassMethods
def value(object, method_name)
object.send method_name unless object.nil?
end
@@ -918,6 +919,10 @@ module ActionView
end
end
+ class InstanceTag
+ include InstanceTagMethods
+ end
+
class FormBuilder #:nodoc:
# The methods which wrap a form helper call.
class_inheritable_accessor :field_helpers
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 292d138fbd..6e71b85645 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -20,6 +20,7 @@ require 'action_controller/testing/process'
require 'action_view/test_case'
require 'action_controller/testing/integration'
require 'active_support/dependencies'
+require 'active_model'
$tags[:new_base] = true
diff --git a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb
index 2a31f3be44..0122bc7d8f 100644
--- a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb
+++ b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb
@@ -126,7 +126,7 @@ class RenderPartialWithRecordIdentificationController < ActionController::Base
end
class Game < Struct.new(:name, :id)
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
def to_param
id.to_s
end
diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb
index 28bc608d47..10f51639cf 100644
--- a/actionpack/test/controller/record_identifier_test.rb
+++ b/actionpack/test/controller/record_identifier_test.rb
@@ -1,7 +1,7 @@
require 'abstract_unit'
class Comment
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
attr_reader :id
def save; @id = 1 end
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 453a77e7bc..a71c39e504 100644
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -4,7 +4,7 @@ class WorkshopsController < ActionController::Base
end
class Workshop
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
attr_accessor :id, :new_record
def initialize(id, new_record)
diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb
index 9e6f14d373..07f01e1c47 100644
--- a/actionpack/test/lib/controller/fake_models.rb
+++ b/actionpack/test/lib/controller/fake_models.rb
@@ -1,7 +1,7 @@
require "active_model"
class Customer < Struct.new(:name, :id)
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
def to_param
id.to_s
@@ -16,7 +16,7 @@ end
module Quiz
class Question < Struct.new(:name, :id)
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
def to_param
id.to_s
diff --git a/actionpack/test/template/active_record_helper_test.rb b/actionpack/test/template/active_record_helper_test.rb
index e1be048838..950072e45b 100644
--- a/actionpack/test/template/active_record_helper_test.rb
+++ b/actionpack/test/template/active_record_helper_test.rb
@@ -4,19 +4,17 @@ class ActiveRecordHelperTest < ActionView::TestCase
tests ActionView::Helpers::ActiveRecordHelper
silence_warnings do
- Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on)
- Post.class_eval do
- alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast)
- alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast)
- alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast)
+ class Post < Struct.new(:title, :author_name, :body, :secret, :written_on)
+ extend ActiveModel::APICompliant
end
- User = Struct.new("User", :email)
- User.class_eval do
- alias_method :email_before_type_cast, :email unless respond_to?(:email_before_type_cast)
+ class User < Struct.new(:email)
+ extend ActiveModel::APICompliant
end
- Column = Struct.new("Column", :type, :name, :human_name)
+ class Column < Struct.new(:type, :name, :human_name)
+ extend ActiveModel::APICompliant
+ end
end
class DirtyPost
diff --git a/actionpack/test/template/atom_feed_helper_test.rb b/actionpack/test/template/atom_feed_helper_test.rb
index 6f1179f359..89ff01ab0e 100644
--- a/actionpack/test/template/atom_feed_helper_test.rb
+++ b/actionpack/test/template/atom_feed_helper_test.rb
@@ -1,7 +1,12 @@
require 'abstract_unit'
-Scroll = Struct.new(:id, :to_param, :title, :body, :updated_at, :created_at)
-Scroll.extend ActiveModel::Naming
+class Scroll < Struct.new(:id, :to_param, :title, :body, :updated_at, :created_at)
+ extend ActiveModel::APICompliant
+
+ def new_record?
+ true
+ end
+end
class ScrollsController < ActionController::Base
FEEDS = {}
diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb
index a7a1bc99f3..301a110076 100644
--- a/actionpack/test/template/prototype_helper_test.rb
+++ b/actionpack/test/template/prototype_helper_test.rb
@@ -1,10 +1,12 @@
require 'abstract_unit'
+require 'active_model'
Bunny = Struct.new(:Bunny, :id)
-Bunny.extend ActiveModel::Naming
+Bunny.extend ActiveModel::APICompliant
class Author
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
+
attr_reader :id
def save; @id = 1 end
def new_record?; @id.nil? end
@@ -14,7 +16,7 @@ class Author
end
class Article
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
attr_reader :id
attr_reader :author_id
def save; @id = 1; @author_id = 1 end
diff --git a/actionpack/test/template/record_tag_helper_test.rb b/actionpack/test/template/record_tag_helper_test.rb
index 5b840d123b..861958ffa9 100644
--- a/actionpack/test/template/record_tag_helper_test.rb
+++ b/actionpack/test/template/record_tag_helper_test.rb
@@ -1,7 +1,7 @@
require 'abstract_unit'
class Post
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
def id
45
end
diff --git a/actionpack/test/template/test_test.rb b/actionpack/test/template/test_test.rb
index f32d0b3d42..98307fbae4 100644
--- a/actionpack/test/template/test_test.rb
+++ b/actionpack/test/template/test_test.rb
@@ -41,7 +41,7 @@ class PeopleHelperTest < ActionView::TestCase
def test_link_to_person
person = mock(:name => "David")
- person.class.extend ActiveModel::Naming
+ person.class.extend ActiveModel::APICompliant
expects(:mocha_mock_path).with(person).returns("/people/1")
assert_equal '<a href="/people/1">David</a>', link_to_person(person)
end
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index f0364fd660..4569689534 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -494,7 +494,7 @@ class LinkToUnlessCurrentWithControllerTest < ActionView::TestCase
end
class Workshop
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
attr_accessor :id, :new_record
def initialize(id, new_record)
@@ -511,7 +511,7 @@ class Workshop
end
class Session
- extend ActiveModel::Naming
+ extend ActiveModel::APICompliant
attr_accessor :id, :workshop_id, :new_record
def initialize(id, new_record)
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index f988cd71b8..c6f63d2fdc 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -26,6 +26,7 @@ $:.unshift(activesupport_path) if File.directory?(activesupport_path)
require 'active_support'
module ActiveModel
+ autoload :APICompliant, 'active_model/api_compliant'
autoload :Attributes, 'active_model/attributes'
autoload :Base, 'active_model/base'
autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods'
diff --git a/activemodel/lib/active_model/api_compliant.rb b/activemodel/lib/active_model/api_compliant.rb
new file mode 100644
index 0000000000..26f83feb6b
--- /dev/null
+++ b/activemodel/lib/active_model/api_compliant.rb
@@ -0,0 +1,25 @@
+module ActiveModel
+ module APICompliant
+ include Naming
+
+ def self.extended(klass)
+ klass.class_eval do
+ include Validations
+ include InstanceMethods
+ end
+ end
+
+ module InstanceMethods
+ def to_model
+ if respond_to?(:new_record?)
+ self.class.class_eval { def to_model() self end }
+ to_model
+ else
+ raise "In order to be ActiveModel API compliant, you need to define " \
+ "a new_record? method, which should return true if it has not " \
+ "yet been persisted."
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index deab56e219..f32857afa3 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -2511,6 +2511,13 @@ module ActiveRecord #:nodoc:
(id = self.id) ? id.to_s : nil # Be sure to stringify the id for routes
end
+ # Returns the ActiveRecord object when asked for its
+ # ActiveModel-compliant representation, because ActiveRecord is
+ # ActiveModel-compliant.
+ def to_model
+ self
+ end
+
# Returns a cache key that can be used to identify this record.
#
# ==== Examples