Wednesday, July 09, 2008

[PLUGIN RELEASE] ActsAsOverflowable

acts_as_overflowable

Written by Nicholas Lega

== DESCRIPTION:

Allows a column to overflow data into a secondary column if the data size exceeds the character limit. This is useful for fast indexing.

Instead of trying to index text blobs, you can specify a varchar column to be used for indexing. Any characters that do not fit into the base column will be automatically saved into or retrieved from an overflow field.


== SYNOPSIS:

Create overflow column migration:


class CreateOverflowModels < ActiveRecord::Migration
def self.up
create_table :overflows do |t|
t.integer :overflowable_id
t.string :overflowable_type
t.string :overflow
t.timestamps
end

add_column(:my_class_that_uses_overflows,
:has_overflow,
:boolean)

add_column(:my_class_that_uses_overflows,
:overflowable_text,
:string,
:limit => 255)
end

def self.down
drop_table :overflows

remove_column(:my_class_that_uses_overflows,
:has_overflow)

remove_column(:my_class_that_uses_overflows,
:overflowable_text)
end
end



Add to model:

class MyClassThatUsesOverflow < ActiveRecord::Base
acts_as_overflowable :overflow_column => :overflowable_text,
:overflow_limit => 255,
:overflow_indicator => :has_overflow,
:overflow_table => :overflows
end



To get and set the value of the "overflowable_text" field as described in the test model, use:

# #{my_field_name_here}_with_overflow is the method name
long_text = overflowable_obj.overflowable_text_with_overflow

overflowable_obj.overflowable_text_with_overflow = very_long_text



Simply using the getters and setters for "overflowable_text" without appending "_with_overflow" to the method name will return the fragment of the text contained in the base column.


== INSTALL:

sudo gem install revolutionhealth-acts_as_overflowable -s http://gems.github.com


== SOURCE:

http://github.com/revolutionhealth/acts_as_overflowable/tree/master


== FEATURES/PROBLEMS:

* Only tested on mysql and sqlite3

Thursday, June 19, 2008

[PLUGIN RELEASE] ActsAsSeoFriendly


ActsAsSeoFriendly

== DESCRIPTION:


Create an SEO friendly field for a model automatically based on a given field.

So if you have a Blogs model, and you would like create an SEO friendly version
of the 'title' field, you would just add this to your model and then be able to
use the SEO friendly id as the unique id to the resource. The plugin will only
append an integer to the SEO id if there is a collision.


== SYNOPSIS:


Create seo column migration:


class CreateSeoTestModels < ActiveRecord::Migration
def self.up
create_table :seo_test_models do |t|
t.string :name
t.timestamps
end
SeoTestModel.create_seo_friendly_column()
end

def self.down
SeoTestModel.drop_seo_friendly_column()
drop_table :seo_test_models
end
end


Add to model:

class SeoTestModel < ActiveRecord::Base
acts_as_seo_friendly :resource_id => :name,
:seo_friendly_id_field => :seo_id, # default is :seo_friendly_id
:seo_friendly_id_limit => 100 # default is 50
end


To lookup the resource in the controllers use:

SeoTestModel.find_by_seo_id(params[:id])


== INSTALL:

sudo gem install revolutionhealth-acts_as_seo_friendly -s http://gems.github.com

== SOURCE:

http://github.com/revolutionhealth/acts_as_seo_friendly/tree/master

To see the plugin in action see our recipes section, for example:


http://www.revolutionhealth.com/recipes/thai-miang-khem-style-salad


== FEATURES/PROBLEMS:

* Only tested on mysql and sqlite3

Thursday, December 13, 2007

ThreadsafeBenchmark

When testing products such as services which need to be stress-tested prior to release, it's necessary to use multi-threading to get as close to real world usage as possible. This gem, though not intended to be a replacement for full-fledged testing suites such as LoadRunner, can provide instantaneous results to facilitate TDD programming. To reduce the duplication of code, the gem utilizes Ruby's built-in Benchmark module for the base functionality while preventing the output from clobbering through the use of thread-specific IO buffers.

require 'threadsafe_benchmark'
include ThreadsafeBenchmark

threads = []
max_num = 5000

5.to_i.times { |i|
threads << Thread.new(max_num) { |n|
threadsafe_bm(6) { |x|
x.report("for:") { for i in 1..n; a = "1"; end }
x.report("times:") { n.times do ; a = "1"; end }
x.report("upto:") { 1.upto(n) do ; a = "1"; end }
}
}
}

threads.each { |t| t.join }

Using the standard Benchmark, the results would be printed haphazardly making it difficult to read and interpret. But ThreadsafeBenchmark cleans everything up giving us nicely laid out columns.

usersystemtotalreal
for0.000000.000000.000000( 0.002889)
times0.000000.000000.000000( 0.002477)
upto0.000000.000000.000000( 0.002479)
for0.000000.000000.000000( 0.002401)
times0.010000.000000.010000( 0.002586)
upto0.000000.000000.000000( 0.002413)
for0.000000.000000.000000( 0.002205)
times0.010000.000000.010000( 0.002245)
upto0.000000.000000.000000( 0.002272)
for0.000000.000000.000000( 0.001822)
times0.010000.000000.010000( 0.001958)
upto0.000000.000000.000000( 0.001943)
for0.010000.000000.010000( 0.010090)
times0.010000.000000.010000( 0.009225)
upto0.010000.000000.010000( 0.007986)

The gem and source files are available at Rubyforge.

Tuesday, November 06, 2007

Enhanced Migrations v1.2.0

The original release of this highly useful plugin marked a turning point in collaborative Rails development by freeing the developer to commit their database migration without fear of having it ignored because of a higher placed migration number. This latest release includes some minor bug fixes plus a useful method for stepping through migrations one at a time without the need for copying and pasting long version numbers.

  1. Fixed bug where an empty migrations_info table would create a non-parseable schema.rb.
  2. Made plugin database independent.
  3. Added capability to step through migrations using VERSION=[previous, next, first and last].
  4. dump_schema_information now returns all migrations, not just latest (credit to Fran├žois Beausolei).
  5. Added tests which use SQLite and a task (enhanced_migrations:clean_sqlite_db) to help with testing.
As an example of item number three, consider the following situation. Using the enhanced migrations plugin, you've just created a migration that adds a new table to your database. Upon running it, you discover that you used the wrong data type for a column. Rather than having to copy and paste the previous migration's version number, simply using 'previous' in the VERSION number will now suffice.

rake db:migrate VERSION=previous
This also works using prev along with next, first and last for their respective operations. Keep in mind that first will go to the first migration and is not the same as VERSION=0.

Migrate as usual

shell> rake db:migrate
== CreateRecipesTable: migrating ==============================================
-- create_table(:recipes)
-> 0.0902s
== CreateRecipesTable: migrated (0.0904s) =====================================

== AddRecipesForUser1: migrating ==============================================
-- execute("INSERT INTO recipes (name, owner) VALUES ('Lemon Meringue Pie', 'user1')")
-> 0.3684s
== AddRecipesForUser1: migrated (0.5302s) =====================================

== AddRecipesForUser2: migrating ==============================================
-- execute("INSERT INTO recipes (name, owner) VALUES ('Steak and Kidney Pie', 'user2')")
-> 0.2574s
== AddRecipesForUser2: migrated (0.3962s) =====================================

Migrate to the previous version

shell> rake db:migrate VERSION=previous
== AddRecipesForUser2: reverting ==============================================
-- execute("DELETE FROM recipes WHERE owner = 'user2'")
-> 0.4512s
== AddRecipesForUser2: reverted (0.4516s) =====================================

Migrate to the first version

shell> rake db:migrate VERSION=first
== AddRecipesForUser1: reverting ==============================================
-- execute("DELETE FROM recipes WHERE owner = 'user1'")
-> 0.1676s
== AddRecipesForUser1: reverted (0.1678s) =====================================

Migrate another previous version, essentially the same as VERSION=0 since we are already at the first migration.

shell> rake db:migrate VERSION=previous
== CreateRecipesTable: reverting ==============================================
-- drop_table(:recipes)
-> 0.1680s
== CreateRecipesTable: reverted (0.1683s) =====================================

How to get
Download the gem from Rubyforge and install it like so:
sudo gem install enhanced_migrations-1.2.1.gem
Update - 11/15/2007
The previous version had a small bug that was discovered during use here that sometimes caused an app's database yaml file to be overwritten by the gem's database config which is used only for testing. The chances of this happening outside of our particular setup are small but we felt it warranted an immediate fix. We've also added a gzip'd source file for the plugin fans out there.

Links in the post have been updated to reflect the location of this new release.

Friday, August 24, 2007

Weblog update

Hey all I wanted to give you an update:

Three of our active contributors are moving on: Aaron, Eddie, and Val. They plan to stay active in the Rails community, as well as new areas like Facebook. You can follow their work at blog.hungrymachine.com. It has been a great pleasure to work with them and we wish them the best.