Showing posts with label rails. Show all posts
Showing posts with label rails. Show all posts

Monday, October 1, 2012

Testing Validations using RSpec

I just ran into an interesting issue while testing a Rails application with RSpec.  A spec with the following line in it was failing:

    ar2.should_not be_valid
Here ar2 is a model that was constructed in a way that violated a logical constraint.  I attempted to make this spec pass by adding a custom validation method to the model as such:
class Registration < ActiveRecord::Base
  validate :fields_match

  private

  def fields_match
    return true if model2.nil?
    model2.model1.id == model1.id
  end
end
All field names have had their names changed to protect their identity.

This didn't work.  As it turns out merely returning false from the validation method isn't enough to mark a model as invalid.  This answer on StackOverflow helped identify the problem as not adding an error to the list of validation errors for the model.

An updated version where I add an error finally made everything pass:

class Registration < ActiveRecord::Base
  validate :fields_match

  private

  def fields_match
    return true if model2.nil?
    return true if model2.model1.id == model1.id
    errors.add(:model2_id, "model2 doesn't match model1")
  end
end

Monday, August 30, 2010

CSV Exports in Rails

If you're looking for an elegant way to generate CSV files from your index views (or search views or anything else for that matter) you should look no further than this post on StackOverflow by rwc9u.

The gist is to add a format line in the respond_to section of the index method in your controller that caters to CSV.  Then create an index.csv.erb file where you can generate the actual CSV using inline ruby like you would for e.g. your index.html.erb view.  Actually retrieving the data in CSV format from your application involves adding a ".csv" extension to the end of your normal index path e.g. /test/widgets becomes /test/widgets.csv to return CSV.

Keep in mind that you'll need to restart your rails server if you create the initializer file that he suggests.

Saturday, March 20, 2010

Switching your Rails Database from SQLite3 to PostgreSQL or MySQL

I deployed a minimal new Rails application I wrote over a period of a couple of hours and started testing it with valid production data.  It's basically a very simple CRUD application for a very specific audience.  Very basic stress testing (using Apache's ab) showed me that it didn't work well when requests were coming in with concurrency > 2. I realized I'd started the project using SQLite3 as the database and that's probably where the bottleneck is since it can handle requests with a concurrency of 1 just fine.  The application is deployed using mod_passenger (my first experience with it) and is configured to never tear down application instances due to idle timeouts.  With 6 application instances listening, a concurrency of 6 should have been a cinch.

In any case, now that I need to switch it to using a real database like PostgreSQL or MySQL, there were no obvious solutions that would allow me to keep the data I already had in my production database.  Everything out there talks about going from development to test to production each of which environments gets their own schema but nothing else.  Migrations allow you to keep your production data in place but that's not the same as dumping it and loading it.  Using database-specific dump/load utilities might result in SQL that needs to be tweaked before it can be loaded into another database type.

In comes the Yaml Db plugin by Orion Henry and Adam Wiggins.  It does exactly what one would expect.  Similar to the way schema.db is database-agnostic, the Yaml Db has a database-agnostic dump format and a similar load format.  One of the specific use cases mentioned on that site is "One common use would be to switch your data from one database backend to another."

Excellent!  Btw, thank you George for the tip!  You know who you are :)

Thursday, March 26, 2009

Multi-Column Database Indices in Sqlite3 and Ruby on Rails

In my previous post about database indices in Sqlite3 and Ruby on Rails, I'd observed that Sqlite didn't seem to support multi-column indices properly. It turns out that while Sqlite does support them, I was using syntax in my Rails model which had the effect of ensuring that both the columns in my index were checked separately for uniqueness. Assuming you have the category_id and name fields in a table such that the combination of those two fields has to be unique, the correct way to do multi-column indices is as follows:
In your database migration,
add_index :contests, [:category_id, :name], :unique => true

In your data model,
validates_uniqueness_of :name, :scope => :category_id
That last line in the model is key. Syntax similar to the add_index line above won't work when using the validates_uniqueness_of validator.

Thursday, March 19, 2009

A Scientific View on Database Indices

I've been playing with Ruby on Rails by seeing how easy (or difficult) it would be for me to re-write an existing mod_perl2 application within RoR. While the original application uses PostgreSQL as its backend database (numerous reasons but the top few are: timestamptz, multiple columns in a table that can default to now(), support for transactions - even nested ones), I decided to use sqlite3 for the initial prototype of the application before it grew beyond 2-3 models.

It seems that either sqlite3 or RoR 2.0.5 doesn't support multi-column indices on a table. One of those two converts a single two-column index into 2 one-column indices - not quite the behavior I wanted. I'll try to switch to PostgreSQL to see if the behavior re-surfaces.

While I was scouring Google for sqlite3's limitations, however, I came across this interesting article that details the kind of scientific analysis that should be conducted on your data to determine the order of columns in a multi-column index. Very informative.