Skip to content

Commit

Permalink
Cache columns for has_and_belongs_to_many associations
Browse files Browse the repository at this point in the history
This avoids repeatedly calling SHOW COLUMNS when the association is queried
[#1738 state:committed]
  • Loading branch information
lukeludwig authored and NZKoz committed Jan 17, 2009
1 parent 9606bc8 commit 7c147e9
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 3 deletions.
Expand Up @@ -9,6 +9,14 @@ def create!(attributes = {})
create_record(attributes) { |record| insert_record(record, true) }
end

def columns
@reflection.columns(@reflection.options[:join_table], "#{@reflection.options[:join_table]} Columns")
end

def reset_column_information
@reflection.reset_column_information
end

protected
def construct_find_options!(options)
options[:joins] = @join_sql
Expand All @@ -32,8 +40,6 @@ def insert_record(record, force=true)
if @reflection.options[:insert_sql]
@owner.connection.insert(interpolate_sql(@reflection.options[:insert_sql], record))
else
columns = @owner.connection.columns(@reflection.options[:join_table], "#{@reflection.options[:join_table]} Columns")

attributes = columns.inject({}) do |attrs, column|
case column.name.to_s
when @reflection.primary_key_name.to_s
Expand Down Expand Up @@ -103,7 +109,7 @@ def construct_scope
# clause has been explicitly defined. Otherwise you can get broken records back, if, for example, the join column also has
# an id column. This will then overwrite the id column of the records coming back.
def finding_with_ambiguous_select?(select_clause)
!select_clause && @owner.connection.columns(@reflection.options[:join_table], "Join Table Columns").size != 2
!select_clause && columns.size != 2
end

private
Expand Down
8 changes: 8 additions & 0 deletions activerecord/lib/active_record/reflection.rb
Expand Up @@ -198,6 +198,14 @@ def counter_cache_column
end
end

def columns(tbl_name, log_msg)
@columns ||= klass.connection.columns(tbl_name, log_msg)
end

def reset_column_information
@columns = nil
end

def check_validity!
end

Expand Down
Expand Up @@ -770,4 +770,15 @@ def test_association_proxy_transaction_method_starts_transaction_in_association_
end
end
end

def test_caching_of_columns
david = Developer.find(1)
# clear cache possibly created by other tests
david.projects.reset_column_information
assert_queries(1) { david.projects.columns; david.projects.columns }
# and again to verify that reset_column_information clears the cache correctly
david.projects.reset_column_information
assert_queries(1) { david.projects.columns; david.projects.columns }
end

end

0 comments on commit 7c147e9

Please sign in to comment.