| Class | BaseRecord |
| In: |
base_record.rb
|
| Parent: | ActiveRecord::Base |
Overrides ActiveRecord::Base to provide support for table_sql. This allows the table name in a query to be replaced with a subquery, essentially simulating a view within ActiveRecord.
Currently, this has only been tested on MySQL 4.1 and Ruby on Rails 0.13.1.
This defines two new class methods set_table_sql and set_table_sql_columns. Both must be used to make a BaseRecord subclass use table_sql. Usually, set_primary_key will have to be called as well (if the primary key of the view is not called id). For example, a ParentDetail class could be defined as:
belongs_to :parent
set_table_sql(<<-TABLE_SQL
SELECT
parents.id parent_id,
SUM(children.attribute) attrib_sum
FROM
parents
INNER JOIN children ON parents.id = children.parent_id
GROUP BY parents.id
TABLE_SQL
)
set_table_sql_columns([
ActiveRecord::ConnectionAdapters::Column.new('parent_id', nil, 'bigint'),
ActiveRecord::ConnectionAdapters::Column.new('attrib_sum', nil, 'bigint')])
set_primary_key('parent_id')
Parent, which should also inherit from BaseRecord, could then be defined as:
has_many :children has_one :parent_detail
You can then perform eager loading finds like the following:
Parent.find(:all, :include => [:parent_detail, other includes...])
This find will produce SQL like the following:
SELECT
parents.id,
other parents fields...,
parent_details.parent_id,
parent_details.attrib_sum,
FROM
parents
LEFT OUTER JOIN (<table sql for ParentDetail>) parent_details ON parent_details.parent_id = parents.id
To upgrade to future versions of ActiveRecord (this was based on RoR 0.13.1, ActiveRecord 1.11.1):
* Check for any changes to the overridden methods and update as necessary:
* columns
* construct_finder_sql
* construct_finder_sql_with_included_associations
* association_join
* class_name_of_active_record_descendant
* attributes_from_column_definition
* Check for any new methods that access connection.columns directly and
override to call table_sql_columns instead.
| set_table_sql | -> | table_sql= |
| set_table_sql_columns | -> | table_sql_columns= |
Overridden to call table_sql_columns rather than connection.columns.
# File base_record.rb, line 175 def attributes_from_column_definition table_sql_columns.inject({}) do |attributes, column| attributes[column.name] = column.default unless column.name == self.class.primary_key attributes end end
Overridden from ActiveRecord::Base to use table_sql_columns rather than a direct call to connection.
# File base_record.rb, line 95 def columns @columns ||= table_sql_columns end
Set the table SQL.
# File base_record.rb, line 70 def set_table_sql( value=nil, &block ) define_attr_method :table_sql, value, &block end
Set the columns to use for table SQL (required if using association eager loading).
# File base_record.rb, line 81 def set_table_sql_columns(value=nil, &block) define_val_attr_method :table_sql_columns, value, &block end
The SQL to use in place of the table name (nil by default => use table_name).
# File base_record.rb, line 65 def table_sql nil end