Permalink
Browse files

Merge pull request #10211 from neerajdotname/4208

fix respond_to? for non selected column
  • Loading branch information...
2 parents 08c6df8 + 66001f3 commit a489bfe48bc0fbbb50a472bc66bd42d408c73fcb @rafaelfranca rafaelfranca committed Apr 19, 2013
View
@@ -1,5 +1,28 @@
## Rails 4.0.0 (unreleased) ##
+* If a query selects only a few columns and gives custom names to
+ those columns then `respond_to?` was returning true for the non
+ selected columns. However calling those non selected columns
+ raises exception.
+
+ post = Post.select("'title' as post_title").first
+
+ In the above case when `post.body` is invoked then an exception is
+ raised since `body` attribute is not selected. Howevere `respond_to?`
+ did not behave correctly.
+
+ pos.respond_to?(:body) #=> true
+
+ Reason was that Active Record calls `super` to pass the call to
+ Active Model and all the columns are defined on Active Model.
+
+ Fix is to actually check if the data returned from the db contains
+ the data for column in question.
+
+ Fixes #4208.
+
+ *Neeraj Singh*
+
* Run `rake migrate:down` & `rake migrate:up` in transaction if database supports.
*Alexander Bondarev*
@@ -163,8 +163,20 @@ def attribute_missing(match, *args, &block) # :nodoc:
# person.respond_to('age?') # => true
# person.respond_to(:nothing) # => false
def respond_to?(name, include_private = false)
+ name = name.to_s
self.class.define_attribute_methods unless self.class.attribute_methods_generated?
- super
+ result = super
+
+ # If the result is false then it means this method is not supported by ActiveModel too
+ return false unless result
+
+ # If the result is true then check for the select case.
+ # For queries selecting a subset of columns, return false for unselected columns.
+ if @attributes.present? && self.class.column_names.include?(name)
+ return has_attribute?(name)
+ end
+
+ return true
end
# Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
@@ -185,6 +185,11 @@ def test_relation_merging_with_merged_joins
assert_equal 3, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count.length
end
+ def test_respond_to_for_non_selected_element
+ post = Post.select("'title' as post_title").first
+ assert !post.respond_to?(:body), "post should not respond_to?(:body) since invoking it raises exception"
+ end
+
end
class RelationMutationTest < ActiveSupport::TestCase

0 comments on commit a489bfe

Please sign in to comment.