From 1a06d324df43bfb3287293934f0ef34a7c790a34 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 27 Feb 2006 00:27:48 +0000 Subject: Define attribute query methods to avoid method_missing calls. Closes #3677. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3679 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activerecord/CHANGELOG | 2 ++ activerecord/lib/active_record/base.rb | 13 ++++++++----- activerecord/test/base_test.rb | 5 +++-- 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 957f13b7f9..549665f28f 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Define attribute query methods to avoid method_missing calls. #3677 [jonathan@bluewire.net.nz] + * ActiveRecord::Base.remove_connection explicitly closes database connections and doesn't corrupt the connection cache. Introducing the disconnect! instance method for the PostgreSQL, MySQL, and SQL Server adapters; implementations for the others are welcome. #3591 [Simon Stapleton, Tom Ward] * Added support for nested scopes #3407 [anna@wota.jp]. Examples: diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 70c44b838d..88baaecfd3 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1544,19 +1544,19 @@ module ActiveRecord #:nodoc: # table with a master_id foreign key can instantiate master through Client#master. def method_missing(method_id, *args, &block) method_name = method_id.to_s - if @attributes.include?(method_name) + if @attributes.include?(method_name) or + (md = /\?$/.match(method_name) and + @attributes.include?(method_name = md.pre_match)) define_read_methods if self.class.read_methods.empty? && self.class.generate_read_methods - read_attribute(method_name) + md ? query_attribute(method_name) : read_attribute(method_name) elsif self.class.primary_key.to_s == method_name id - elsif md = /(=|\?|_before_type_cast)$/.match(method_name) + elsif md = /(=|_before_type_cast)$/.match(method_name) attribute_name, method_type = md.pre_match, md.to_s if @attributes.include?(attribute_name) case method_type when '=' write_attribute(attribute_name, args.first) - when '?' - query_attribute(attribute_name) when '_before_type_cast' read_attribute_before_type_cast(attribute_name) end @@ -1610,12 +1610,15 @@ module ActiveRecord #:nodoc: unless attr_name.to_s == self.class.primary_key.to_s access_code = access_code.insert(0, "raise NoMethodError, 'missing attribute: #{attr_name}', caller unless @attributes.has_key?('#{attr_name}'); ") self.class.read_methods << attr_name + self.class.read_methods << "#{attr_name}?" end begin self.class.class_eval("def #{symbol}; #{access_code}; end") + self.class.class_eval("def #{symbol}?; query_attribute('#{attr_name}'); end") rescue SyntaxError => err self.class.read_methods.delete(attr_name) + self.class.read_methods.delete("#{attr_name}?") if logger logger.warn "Exception occured during reader method compilation." logger.warn "Maybe #{attr_name} is not a valid Ruby identifier?" diff --git a/activerecord/test/base_test.rb b/activerecord/test/base_test.rb index 4349d92eeb..4cdf24c03d 100755 --- a/activerecord/test/base_test.rb +++ b/activerecord/test/base_test.rb @@ -1163,7 +1163,8 @@ class BasicsTest < Test::Unit::TestCase private def assert_readers(model, exceptions) - expected_readers = model.column_names - (model.serialized_attributes.keys + exceptions + ['id']) - assert_equal expected_readers.sort, model.read_methods.to_a.sort + expected_readers = Set.new(model.column_names - (model.serialized_attributes.keys + exceptions + ['id'])) + expected_readers += expected_readers.map { |col| "#{col}?" } + assert_equal expected_readers, model.read_methods end end -- cgit v1.2.3