Skip to content

Instantly share code, notes, and snippets.

@reynaldot
Created February 11, 2011 01:36
Show Gist options
  • Save reynaldot/821763 to your computer and use it in GitHub Desktop.
Save reynaldot/821763 to your computer and use it in GitHub Desktop.
ActiveRecord 2.3.8 - Associations + namescoped models patch.
# ActiveRecord 2.3.8 - Associations + namescoped models patch.
#
# Problem:
# module App::Model
# class Base < ActiveRecord::Base
# # some base class logic...
# end
#
# class User < App::Model::Base
# set_table_name :users
# # Associations:
# has_many :settings, :as => :configurable
# end
#
# class Setting < App::Model::Base
# set_table_name :settings
# # Associations:
# belongs_to :configurable, :polymorphic => true
# end
# end
#
# Creating a setting for a user:
#
# user = User.first
# user.settings << Setting.new
#
# Produces a record with a 'configurable_type' column
# value 'App::Model::Base' instead of 'App::Model::User'.
#
# Solution:
# replaced '@owner.class.base_class.name.to_s'
# with '@owner.class.name.to_s'
#
module ActiveRecord
module Associations
class AssociationProxy
def set_belongs_to_association_for(record)
if @reflection.options[:as]
record["#{@reflection.options[:as]}_id"] = @owner.id unless @owner.new_record?
record["#{@reflection.options[:as]}_type"] = @owner.class.name.to_s
else
unless @owner.new_record?
primary_key = @reflection.options[:primary_key] || :id
record[@reflection.primary_key_name] = @owner.send(primary_key)
end
end
end
end
class 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.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 @reflection.options[:finder_sql]
# 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
class HasOneAssociation
def construct_sql
case
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.name.to_s)}"
else
@finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
end
@finder_sql << " AND (#{conditions})" if conditions
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment