Skip to content

Instantly share code, notes, and snippets.

@funny-falcon
Created September 24, 2010 07:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save funny-falcon/594976 to your computer and use it in GitHub Desktop.
Save funny-falcon/594976 to your computer and use it in GitHub Desktop.
class ActiveRecord::Associations::AssociationCollection
def has_finder_sql_with_select?
@finder_sql =~ /^\s*select\s/i
end
def find(*args)
options = args.extract_options!
# If using a custom finder_sql, scan the entire collection.
if has_finder_sql_with_select?
expects_array = args.first.kind_of?(Array)
ids = args.flatten.compact.uniq.map { |arg| arg.to_i }
if ids.size == 1
id = ids.first
record = load_target.detect { |r| id == r.id }
expects_array ? [ record ] : record
else
load_target.select { |r| ids.include?(r.id) }
end
else
conditions = "#{@finder_sql}"
if sanitized_conditions = sanitize_sql(options[:conditions])
conditions << " AND (#{sanitized_conditions})"
end
options[:conditions] = conditions
if options[:order] && @reflection.options[:order]
options[:order] = "#{options[:order]}, #{@reflection.options[:order]}"
elsif @reflection.options[:order]
options[:order] = @reflection.options[:order]
end
# Build options specific to association
construct_find_options!(options)
merge_options_from_reflection!(options)
# Pass through args exactly as we received them.
args << options
@reflection.klass.find(*args)
end
end
def find_target
records =
if has_finder_sql_with_select?
@reflection.klass.find_by_sql(@finder_sql)
else
find(:all)
end
records = @reflection.options[:uniq] ? uniq(records) : records
records.each do |record|
set_inverse_instance(record, @owner)
end
records
end
def fetch_first_or_last_using_find?(args)
args.first.kind_of?(Hash) ||
!(loaded? || @owner.new_record? || has_finder_sql_with_select? ||
@target.any? { |record| record.new_record? } || args.first.kind_of?(Integer))
end
end
class ActiveRecord::Associations::HasManyAssociation
def construct_sql
case
when @reflection.options[:finder_sql]
@finder_sql = interpolate_sql(@reflection.options[:finder_sql])
when @reflection.options[:as]
@finder_sql =
"#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND " +
"#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}"
@finder_sql << " AND (#{conditions})" if conditions
else
@finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
@finder_sql << " AND (#{conditions})" if conditions
end
if @reflection.options[:counter_sql]
@counter_sql = interpolate_sql(@reflection.options[:counter_sql])
elsif has_finder_sql_with_select?
# replace the SELECT clause with COUNT(*), preserving any hints within /* ... */
@reflection.options[:counter_sql] = @reflection.options[:finder_sql].sub(/SELECT (\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" }
@counter_sql = interpolate_sql(@reflection.options[:counter_sql])
else
@counter_sql = @finder_sql
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment