ar-extensions, Rails 2.x followup
on July 18, 2008 @ 01:41 AM

First things first, ar-extensions moved to Lighthouse and Github. So please no more tickets or patches on rubyforge. I’ll close out or move over the ones on rubyforge that currently reside there.

Now, the fun stuff.

ar-extensions and Rails 2.x compability

For the most part ar-extensions 0.7.0 (and below) is not compatible with Rails 2.0.x and 2.1. The import functionality works, but ar-extensions will bork on some edge cases of using ActiveRecord::Base.find methods. It won’t return the wrong value, it will simply raise an exception. So if you’re using ar-extensions in your Rails 2.x app, the app itself will probably bork (and I realize that you probably already know this). If you’re using the import functionality in isolation then you should be fine.

Some of the loading issues with ar-extensions that people had are due to ar-extensions being loaded during the time that Rails goes through the loading process (if you put require ‘ar-extensions’ in config/environments/development.rb, test.rb or production.rb). You can get around this by moving if after the Rails::Initializer.run block in your config/environment.rb file.

Tonight I made several commits to get ar-extensions closer to Rails 2.1.0 compatibility. HEAD right now is Rails 2.0.1 compatible, but not 2.0.2 or 2.1.0 compatible. As soon as ar-extensions is compatible I will release 0.8.0. I am hoping for it to be released within the next few days. And by compatible I mean that ar-extensions not only passes its own tests, but it also doesn’t break any of ActiveRecord’s tests.

3 comments | Filed Under: | read on

ar-extensions, Rails 2.x
on July 17, 2008 @ 02:34 AM

There are some issues with ar-extensions and Rails 2.x. At first glance it mainly has to do with load order and what to load. I’m going to try to post an update or at least instructions tomorrow so people can use ar-extensions with Rails 2.x and up.

I’m going to be moving the codebase to github and will start work on ar-extensions to get closer to a 1.0 release later this fall. I plan to kick out 0.8 which includes some bug fixes and any Rails 2.x issues as soon as possible.

I am also looking into using Lighthouse for tickets. Rubyforge’s bug tracking isn’t the greatest and apparently there have been tickets there for a while that I had no idea about (sorry about that).

0.9 will be the first release where I look to improve and cleanup the codebase. Thanks for your patience.

Any questions, comments or suggestions feel free to let me know. Thanks,

0 comments | Filed Under: | read on

ar-extensions get a little praise
on January 20, 2008 @ 09:52 PM

Alan Miles found the import functionality of my ar-extensions gem/plugin helpful and he posted about it here

I’m so glad to hear that ar-extensions is helping Alan and it’s nice to see that he’s sharing this usefulness with others via his blog

1 comment | Filed Under: | read on

ActiveRecord::Extensions 0.7.0 Released!
on July 21, 2007 @ 06:37 AM

ActiveRecord::Extensions 0.7.0 is released! Thanks to Michael Flester and Gabe da Silveira for the patches they submitted!

Updates include:

  • Oracle support for better finders (but regexps only work with Oracle 10 or higher) and import (Michael Flester)
  • created_at/updated_at timestamps are now implemented with import functionality if they exist on the tables (Zach Dennis/Michael Flester)
  • fixed padding issue with MySQL by increasing the byte buffer size to 8 bytes. (thanks to Gabe da Silveira)

To install as a gem you can run:

gem install ar-extensions

To update a previously installed gem you can run:

gem update ar-extensions

To install as a script/plugin you can run:

script/plugin install http://arext.rubyforge.org/svn/tags/ar-extensions-0.7.0

To see information on the usage of ar-extensions please refer to the arext page or refer to the RDOC documentation

Enjoy!

For questions, comments please feel free to email me, zach dot dennis at gmail dot com or by submitting to rubyforge project page for arext.

3 comments | Filed Under: | read on

Rails patch 8277
on May 06, 2007 @ 05:11 AM

The synchronize functionality released in ActiveRecord::Extensions 0.6.0 should probably go in core. So I submitted a patch

My reasoning is that is ActiveRecord::Base#reload already works on a per instance level, why not allow it work on a class level where the class can efficiently handle reloads on multiple instances at once.

The benefit of the class level reload is that you can do one query to the database regardless of how many instances you have rather then having to perform one query per instance.

If you’re in favor of the patch please encourage it gets accepted.

0 comments | Filed Under: | read on

ActiveRecord::Extensions 0.6.0 released
on May 06, 2007 @ 04:34 AM

ActiveRecord::Extensions 0.6.0 is released! You can install it via RubyGems:


gem install ar-extensions

What’s New?

0.6.0 includes:
  • support for arrays when using the Hash arguments and the ‘_contains’ suffix.
  • a synchronize method which acts like ActiveRecord::Base#reload, but it works on multiple instances. The benefit being that it makes one query to reload all instances rather then one query per instance
  • a bug fix for URI encoded strings when using find with ActiveRecord objects

Examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# synchronize example
post = BlogPost.find_by_author_name( 'zdennis' )
columns = [ :author_name, :title ]
values = [ [ 'yoda', 'test post' ] ]
BlogPost.import columns, values, :synchronize=>[ post ]
post.author_name # => 'yoda'

# using synchronize option with import
posts = BlogPost.find(:all)
BlogPost.import( columns, values, :synchronize=>posts)

# using arrays with the _contains suffix
BlogPost.find( 
  :all,  
  :conditions=>{ :author_name_contains=>[ 'ab', 'oc', 'ed' ] } )

Questions, Comments

zach dot dennis at gmail dot com

0 comments | Filed Under: | read on

ActiveRecord::Extensions 0.5.2 Released!
on March 15, 2007 @ 01:32 AM

ActiveRecord::Extensions 0.5.2 is released! A rubygem has been born!

Installation is so easy now for ActiveRecord::Extensions:


gem install -r 'ar-extensions'

Enjoy!

0.5.1 was also released, but I quickly released 0.5.2 after it to fix a possible bug with method aliasing. This would only occur if you had another plugin or rubygem which used the same alias name for ActiveRecord::Base#quote

4 comments | Filed Under: AREruby | read on

ActiveRecord::Extensions 0.5.0 Released!
on March 14, 2007 @ 02:14 AM

ActiveRecord::Extensions 0.5.0 is released! This release includes support for querying against Time objects against ActiveRecord columns which are considered :datetime by ActiveRecord’s standards .

Code Example

To find all blog posts within the last week:


BlogPost.find( :all, :conditions=>{ :created_at_gt => Time.now-1.week } )

To find all posts within the last year:


BlogPost.find( :all, :conditions=>{ :created_at_gt => Time.now-1.year } )

To find all posts over a year old:


BlogPost.find( :all, :conditions=>{ :created_at_lt => Time.now-1.year} )
To find all users who logged in within the past 15 minutes:

User.find( :all, :conditions=>{ :logged_in_at_gt => Time.now-15.minutes} )

Supported Suffix Modifiers

This particular query addition supports the following column name suffix modifiers (ie: the “_lt” in the “created_at_lt”).
  • _lt => less than
  • _gt => greater than
  • _lte => less than or equal to
  • _gte => greater than or equal to
  • _ne => not equal to
  • _not => not equal to
  • eq => equal to _(this is implied without a suffix present)

MySQL TIMESTAMP Disclaimer

This does not work on TIMESTAMP columns for MySQL due to an issue with the inconsistency of TIMESTAMP columns in varying versions of MySQL and due to the nature of server configurations which can alter the behavior of TIMESTAMP columns.

PostgreSQL Support Note

I recently switched to a Mac, I am compiling PostgreSQL 8.1 and 8.2 as I type this. As soon as I can test this functionality against PostgreSQL I will release an update with that support.

Download It Now!

0 comments | Filed Under: AREruby | read on

ActiveRecord::Extensions 0.4.0 Released!
on February 12, 2007 @ 02:22 AM

ActiveRecord::Extensions 0.4.0 is released!

Updates

  • added to_csv functionality (works with belongs_to, has_one and has_many relationships)
  • added temporary table functionality
  • added foreign key functionality

to_csv functionality

Example 1, exporting all fields

1
2
3
4
 class Book < ActiveRecord::Base ; end

 book = Book.find( 1 )
 book.to_csv

Example 2, only exporting certain fields

1
2
3
4
 class Book < ActiveRecord::Base ; end

 book = Book.find( 1 )
 book.to_csv( :only=>%W( title isbn )

Example 3, exporting a model including a belongs_to association

1
2
3
4
5
6
 class Book < ActiveRecord::Base
   belongs_to :author
 end

 book = Book.find( 1 )
 book.to_csv( :include=>:author )

This also works for a has_one relationship. The :include option can also be an array of has_one/belongs_to associations. This by default includes all fields on the belongs_to association.

Example 4, exporting a model including a has_many association

1
2
3
4
5
6
 class Book < ActiveRecord::Base
   has_many :tags
 end

 book = Book.find( 1 )
 book.to_csv( :include=>:tags )

This by default includes all fields on the has_many assocaition. This can also be an array of multiple has_many relationships. The array can be mixed with has_one/belongs_to associations array as well. IE: :include=>[ :author, :sales ]

Example 5, nesting associations

1
2
3
4
5
6
7
8
9
 class Book < ActiveRecord::Base
   belongs_to :author
   has_many :tags
 end

 book = Book.find( 1 )
 book.to_csv( :include=>{
                 :author => { :only=>%W( name ) },
                 :tags => { :only=>%W( tagname ) } )

Example 6, using Arrays returned by find

1
2
3
4
5
6
7
8
9
 class Book < ActiveRecord::Base
   belongs_to :author
   has_many :tags
 end

 books = Book.find( :all )
 books.to_csv( :include=>{
                 :author => { :only=>%W( name ) },
                 :tags => { :only=>%W( tagname ) } )

Temporary Table Support

Example 1, using defaults

1
2
3
 class Project < ActiveRecord::Base ; end

 Project.create_temporary_table

This creates a temporary table named ‘temp_projects’ and creates a constant name TempProject. The table structure is copied from the projects table.

Example 2, using :table_name and :model options


  Project.create_temporary_table :table_name=>'my_projects', :model=>'MyProject'

This creates a temporary table named ‘my_projects’ and creates a constant named MyProject. The table structure is copied from the projects table.

Example 3, using :like


  ActiveRecord::Base.create_temporary_table :like=>Project

This is the same as calling Project.create_temporary_table.

Example 4, using block form

1
2
3
  Project.create_temporary_table do |t|
    # ...
  end

Using the block form will automatically drop the temporary table when the block exits. t which is passed into the block is the temporary table class. In the above example t equals TempProject. The block form can be used with all of the available options.

Foreign Key Support

Enables support for enabling and disabling foreign keys for the underlying database connection for ActiveRecord. This can be used with or without block form. This also uses the connection attached to the model.

Example 1, without block form

1
2
  Project.foreign_keys.disable
  Project.foreign_keys.enable

If you use this form you have to manually re-enable the foreign keys.

Example 2, with block form

1
2
3
4
5
6
7
  Project.foreign_keys.disable do
    # ...
  end

 Project.foreign_keys.enable do
   # ...
 end

If you use the block form the foreign keys are automatically enabled or disabled when the block exits. This currently does not restore the state of foreign keys to the state before the block was entered.

Download It Now!

ActiveRecord::Extensions 0.4.0

Check it out from SVN into your Rails project

svn co svn://rubyforge.org/var/svn/arext/tags/ar-extensions-0.4.0 vendor/plugins/
4 comments | Filed Under: AREruby | read on

Temporary Table Nicety
on January 31, 2007 @ 05:53 AM

A taste of temporary table support for ActiveRecord and MySQL.

Creating Temporary Tables

Temporary tables can be created by using two forms. Temporary tables will generate the following SQL:


CREATE TEMPORARY TABLE table_name LIKE base_table

The First Form

A block form which manages your temporary table (ie: it creates the table at the start of the block and ensures it is removed by the end of the block, similar to how IO objects work in ruby) .

The Second Form

The second form allows you to assign your temporary table to a variable. You are responsible for destroying it. Or you could just leave it around until your ruby process is done and your database will kill it when the connection closes.

Here’s an example using the block form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# create our model
class Account < ActiveRecord::Base
end

# perform the update
Account.create_temporary_table do |t|
   t.new.is_a? ActiveRecord::Base # => true
   t.new.is_a? ActiveRecord::TemporaryTable # => true

    # You can treat 't' like any model class, and create new records, 
    # add validations, etc.
    record = t.new :name=>"New Account" 
    record.save
    record.create :name => "Another new account"

    # TempAccount is created to reference this model class as well
     TempAccount == t # => true

    # the "end" block here will drop our temporary table and remove
    # our TempAccount constant
end

Checking It Out

You can pull it down from trunk right now. It will be included in the next release (which will be 0.4.0):
  • svn checkout svn://rubyforge.org/var/svn/arext/trunk/ar-extensions

Like Tables

Like tables are similar to temporary tables. In fact they are created in the exact same way except that they are permanent. They are normal tables until you destroy them. A like table simply generates the following sql:


CREATE TABLE table_name LIKE base_table

You can create this the same way way you create temporary tables, just pass in the :permanent option as a parameter:

1
2
3
4
5
6
7
8
9
10
class Account < ActiveRecord::Base
end

# t is your model class, also aliased as TempAccount.
temp_account_model_class = Account.create_temporary_table :permanent=>true

TempAccount == temp_account_model_class # => true  
   
# drop your table
TempAccount.drop
1 comment | Filed Under: AREruby | read on

ActiveRecord Foreign Key Nicety
on January 24, 2007 @ 09:47 PM

I’ve been busy lately and I haven’t finished the to_csv functionality for ActiveRecord::Extensions. It’s coming, but I haven’t had time to implement all of the tests.

A new feature that myself and Mark Van Holstyn worked up was because we wanted an elegant solution to this in a problem we had. And it was time to finally put in the foreign key support that I hacked together over a year ago. Now it’s not a hack, and I think it’s kind of elegant.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Disable foreign keys altogether
ActiveRecord::Base.foreign_keys.disable

# Enable foreign keys 
ActiveRecord::Base.foreign_keys.enable

# Run some updates in a disable block and have AR automatically re-enable foreign keys
Topic.foreign_keys.disable do
   # ... code here....
end

# Run some updates in a enable block and have AR automatically re-disable foreign keys
Topic.foreign_keys.enable do
   # ... code here ....
end

This works on any instance of ActiveRecord::Base, and it works on the connection for that instance. So if you have models which are connected to different databases, no worries.

This is in trunk right now and works great for MySQL.

0 comments | Filed Under: | read on

to_csv update (nearing Round #2)
on January 04, 2007 @ 07:17 AM

Round #2 of the to_csv functionality is nearing completion. The updates so far are:
  • supports associations via the :include option on a per model object basis
  • supports custom headers through the model class

It will work on an ActiveRecord model object itself or an array of ActiveRecord model objects that are returned from any “find” method call.

Basic :include option

The :include option will bring in an association that is created with belongs_to or has_many declarations.

Here is a basic example for a belongs_to association to be included in the CSV results with default options:


csv = People.find( :all ).to_csv( :include=> [ :address ] )
If you haven’t been following to_csv functionality prior to this posting the to_csv method does support toggling on/off of the CSV headers:
  • :headers=>true
  • :headers=>false

Updated :headers Option

To detour from the :include options for a moment, the :headers option has been updated to accept:
  • an array of column names as Symbols or Strings
  • a Hash of column name to header name mappings as Symbols or Strings

Here are a few examples of the new headers option in use:

1
2
3
4
5
6
7
8
# using symbols
csv = People.find( :all ).to_csv( :headers => [ :first_name, :last_name ]  }

# using strings
csv = People.find( :all ).to_csv( :headers => [ 'first_name', 'last_name' ]  }

# using a Hash to supply custom headers
csv = People.find( :all ).to_csv( :headers => { :first_name=>'FirstName', :last_name=>'LastName' }

Since Arrays are ordered the CSV columns will be in the order of the Array. Since Hashes aren’t ordered the order of the columns will be done alphabetically based on the field name.

Intermediate Usage Of :include

The :include option can take:
  • an Array of Strings or Symbols denoting the name of the association
  • a Hash of Hashes mapping the association name to an options Hash

The options Hash is what you’re already passing into the to_csv method. If you use the Hash form of :include you get the ability to embed different options per each association included.

Here are some more intermediate examples:

1
2
3
4
5
6
7
8
9
10
11
12
13
people = People.find( :all )

# Using a Hash to specify the column you want from the Address relationship
people.to_csv( :include=>{ :address=>{ :only=>[ :street, :city, :state, :zip ] } } )

# Using a top level options to include only certain fields from each person and
# then options to include certain fields from each person's address.
people.to_csv( :only=>[ :first_name, :last_name ],
   :include=>{ :address=>{ :only=>[ :street, :city, :state, :zip ] } } )

# Modification of the last example to use custom headers
people.to_csv( :headers=>{ :first_name=>"FName", :last_name=>"LName" } ,
   :include=>{ :address=>{ :headers=>{ :city=>"Hometown", :state=>"ST" } } } )

That’s a brief summary for where the state of affairs is at for now. If you want more information please read all of the nice tests by checking out the SVN repository.

There are some other usages that you will be able to do like (see below) but the tests and functionality has not been intentionally implemented although it may/may work off from existing functionality:
  • support multiple :include options for multiple associations
  • embed :include options inside of :include options for chaining associations

One thing I don’t like about all of this so far is all of the curly braces, brackets and potentially parenthesizes. The more :includes you want to have, the more curly braces you’re going to have most likely.

I’m trying to think of a block like declarative syntax to handle this, but I haven’t come up with any worthwhile yet. If you’ve got any ideas I’m all ears.

Upcoming 0.4.0 release

This will be launched in a 0.4.0 release which should be soon. I’ve got to be out of town part of this weekend, and the most of next week so I am going to see if I can crunch it in before the next Monday.

1 comment | Filed Under: AREruby | read on

ActiveRecord::Extensions 0.3.0 Released!
on December 30, 2006 @ 12:50 AM

ActiveRecord::Extensions 0.3.0 is released! Download it here.

There are no functionality changes in this release. There are two changes:
  • thanks to Michael Schuerig for pointing out a potential namespace issue which is fixed in this release
  • tests are now loaded in the a new ruby process rather then into the same ruby process as rake tasks when running rake test:
0 comments | Filed Under: AREruby | read on

ActiveRecord::Extensions 0.2.0 Released!
on December 22, 2006 @ 07:50 AM

ActiveRecord::Extensions 0.2.0 is released! Download it here .

Updates include:
  • Changes to the to_csv method to support an API compatible with the ToCSV plugin by Chris Abad
  • Added support for SQLite and SQLite3
  • Added “does_not_match” suffix for :conditions which want to negate a regex
  • Added “not_between” suffix for :conditions which want to negate a range
  • Converted test database schema to use migrations, and added tasks to load test database

to_csv updates

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  class Developer < ActiveRecord::Base ; end
  developers = Developer.find( :all )

  # Output default headers, this is implicit if headers is not provided
  csv  = developers.to_csv( :headers => true )

  # Output no headers
  csv = developers.to_csv( :headers => false )

  # Output only the following columns
  csv = developers.to_csv( :only=>[ :id, :name ] )
 
  # Output all columns except the following
  csv = developers.to_csv( :except => [ :id, :name ] )

Updates to better finders

I was typing some code today and I was using Ranges and Regexps. It just felt write to say that something_does_not_match when matching between a Regular Expression. And then I decided to add “not_between” for Ranges.

1
2
3
4
5
6
7
  class Developer < ActiveRecord::Base ; end
  
  # find all developers whose name does not match the regex
  Developer.find :all, :conditions => { :name_does_not_match => '^Zach' }

  # find all developers whose IQ is not between 80 and 120
  Developer.find :all, :conditions => { :iq_not_between => ( 80 .. 120 ) }

Running ActiveRecord::Extensions Tests

ActiveRecord::Extensions provides a great testing suite. Just run “rake -T” to see all of the supported tasks. In 0.2.0 the ability to load a test database from migrations has been added.

     # Usage
     rake db:test:prepare_<db>

     # IE:
     rake db:test:prepare_mysql

     # Then run your tests:
     rake test:mysql

     # And don't forget to test against activerecord
     rake test:activerecord:mysql ~/rails_trunk/activerecord 

The only prerequisite of the above is to make sure that your connection is specified correctly for the database you want to test. To do this go into the tests/connections/native_/connection.rb file and update the database configuration.

Enjoy 0.2.0!

For any questions or comments let me know.
  • zach DOT dennis AT gmail DOT com
0 comments | Filed Under: AREruby | read on

ActiveRecord::Extensions SQLite Compatibility
on December 21, 2006 @ 03:18 AM

The upcoming 0.2.0 release is going to include SQLite compatibility, and it looks like that is going to be released before the weekend hits! Any one out there who uses SQLite and wants to leverage the usefulness of ActiveRecord::Extensions, wait no longer (then 1 to 2 more days)!

The upcoming 0.2.0 release will update the to_csv and to_csv_file method arguments.

1
2
3
4
5
6
7
8
9
10
11
# rather then
array_of_models.to_csv( :headers => [ :field1, :field2, :field3 ] )

# it'll be
array_of_models.to_csv( :headers => true|false, :only=> [ :field1, :field2, :field3 ] )

# or
array_of_models.to_csv( :headers => true|false, :except=> [ :id ] )

# and the same goes for the options that were passed into to_csv_file as well
array_of_models.to_csv_file( filename, :headers=>[ :name, :salary ] )

Thanks to Dan Kubb for bringing this up. The API is borrowed from Chris Abad’s ToCSV plugin.

After that I’ll be on holiday vacation and I hope to kick out some cool stuff, like the :include option that Dan Kubb mentioned. for the to_csv.

0 comments | Filed Under: AREruby | read on