Module: ActiveRecord::Extensions

Extended by:
Forwardable
Defined in:
lib/ar-extensions/version.rb,
lib/ar-extensions/extensions.rb,
lib/ar-extensions/create_and_update.rb,
lib/ar-extensions/util/sql_generation.rb,
lib/ar-extensions/util/support_methods.rb

Overview

ActiveRecord::Extensions provides additional functionality to the ActiveRecord ORM library created by DHH for Rails.

It’s main features include:

  • better finder support using a :conditions Hash for ActiveRecord::Base#find

  • better finder support using any object that responds to the to_sql method

  • mass data import functionality

  • a more modular design to extending ActiveRecord

Using Better Finder Hash Support

Here are a few examples, please refer to the class documentation for each extensions:

class Post < ActiveRecord::Base ; end

Post.find( :all, :conditions=>{ 
  :title => "Title",                           # title='Title'
  :author_contains => "Zach",                  # author like '%Zach%'
  :author_starts_with => "Zach",               # author like 'Zach%'
  :author_ends_with => "Dennis",               # author like '%Zach'
  :published_at => (Date.now-30 .. Date.now),  # published_at BETWEEN xxx AND xxx
  :rating => [ 4, 5, 6 ],                      # rating IN ( 4, 5, 6 )
  :rating_not_in => [ 7, 8, 9 ]                # rating NOT IN( 4, 5, 6 )
  :rating_ne => 4,                             # rating != 4
  :rating_gt => 4,                             # rating > 4
  :rating_lt => 4,                             # rating < 4
  :content => /(a|b|c)/                        # REGEXP '(a|b|c)'
)

Create Your Own Finder Extension Example

The following example shows you how-to create a robust and reliable finder extension which allows you to use Ranges in your :conditions Hash. This is the actual implementation in ActiveRecord::Extensions.

class RangeExt 
  NOT_IN_RGX = /^(.+)_(ne|not|not_in|not_between)$/

  def self.process( key, val, caller )
    return nil unless val.is_a?( Range )
    match_data = key.to_s.match( NOT_IN_RGX )
    key = match_data.captures[0] if match_data
    fieldname = caller.connection.quote_column_name( key )
    min = caller.connection.quote( val.first, caller.columns_hash[ key ] )
    max = caller.connection.quote( val.last, caller.columns_hash[ key ] )
    str = "#{caller.quoted_table_name}.#{fieldname} #{match_data ? 'NOT ' : '' } BETWEEN #{min} AND #{max}"
    Result.new( str, nil )
 end

Using to_sql Ducks In Your Find Methods!

The below example shows you how-to utilize objects that respond_to the method to_sql in your finds:

class InsuranceClaim < ActiveRecord::Base ; end

class InsuranceClaimAgeAndTypeQuery
  def to_sql
     "age_in_days BETWEEN 1 AND 60 AND claim_type IN( 'typea', 'typeb' )"
  end
end

claims = InsuranceClaim.find( :all, InsuranceClaimAgeAndTypeQuery.new )

claims = InsuranceClaim.find( :all, :conditions=>{
  :claim_amount_gt => 30000,
  :age_and_type => InsuranceClaimAgeAndTypeQuery.new } 
)

Importing Lots of Data

ActiveRecord executes a single INSERT statement for every call to ‘create’ and for every call to ‘save’ on a new model object. When you have only a handful of records to create or save this is not a big deal, but when you have hundreds, thousands or hundreds of thousands of records you need to have better performance.

Below is an example of how to import the least amount of INSERT statements using mechanisms provided by your database vendor:

class Student < ActiveRecord::Base ; end

column_names = Student.columns.map{ |column| column.name }
value_sets = some_method_to_load_data_from_csv_file( 'students.csv' )
options = { :valudate => true }

Student.import( column_names, value_sets, options )

The import functionality can be used even if there is not specific support for you vendor. This happens when a particular database vendor specific enhancement hasn’t been added to ActiveRecord::Extensions. You can still use import though because the import functionality has been created with backwards compatibility. You may still get better performance using import, but you will definitely get no worse then ActiveRecord’s create or save methods.

See ActiveRecord::Base.import for more information and other ways to use this functionality.

Developers

  • Zach Dennis

  • Mark Van Holsytn

Homepage

Defined Under Namespace

Modules: ConnectionAdapters, CreateAndUpdate, Delete, FindToCSV, FinderOptions, ForeignKeys, FullTextSearching, Import, InsertSelectSupport, SqlGeneration, SupportMethods, TemporaryTableSupport, Union, VERSION Classes: ArrayExt, Comparison, DatetimeSupport, Like, MySQLRegexp, OracleRegexp, PostgreSQLRegexp, RangeExt, RegexpBase, Registry, Result, SqliteRegexp

Class Method Summary collapse

Class Method Details

.register(extension, options) ⇒ Object

:nodoc:



156
157
158
159
# File 'lib/ar-extensions/extensions.rb', line 156

def register( extension, options ) # :nodoc:
  @registry ||= Registry.new
  @registry.register( extension, options )
end