Output table column names to a file

November 15th, 2011

I’m working on tool to transfer data from one database to another. I wanted a list of column names in a file so that I had a list I could work through. After a hunt around the MySQL docs I found mysqlshow, which works a treat:

  mysqlshow -u username -p password database_name table_name > output.txt

Do not put hyphens in engine names

September 26th, 2011

I’m currently working on my first rails 3.1 engine and have just wasted a day or so because I put a hyphen in the engine name. The reason I did this was to be consistent with some other plug-ins I am using (e.g. noodall-core). The new plugin should provide polls for noodall sites. So noodall-poll would be consistent with other noodall plugins.

rails plugin new NoodallPoll --mountable

Created noodall_poll.

So instead I used:

rails plugin new noodall-poll --mountable

The result was lots of paths using noodall-poll, such as /app/helpers/noodall-poll/application_helper.rb. When I tried to run test, I got application_helper.rb not found errors. The system was looking for /app/helpers/noodall_poll/application_helper.rb.

Lesson learn: don’t play around with engine names. Use camelcase or underscored engine names.

My first gem: Acts As Soft Delete By Field

August 5th, 2011

I’ve had a bit of spare time recently, so I thought it was about time that I created a public gem. I thought about my code and decided that my soft delete system would be a good place to start. I’d created it about three years ago and it’s been used in a couple of corporate projects. It is also fairly simple and self contained.

It had been created in a somewhat pragmatic way, using the simplest way that I could find to implement it. That was to create the functionality in an ActiveRecord::Base abstract class, and then have all the models that needed this functionality, inherit this class. I’ve made the code available as SoftDeleteableBase.

This approach works fine and is very easy to implement. The problem is that it does not scale very well. That is, if you need to add additional functionality in the same way, the new abstact class has to inherit from the original.

A much better way to add functionality to a model is by mixing in via a module. Having recently read Elequent Ruby by Russ Olsen (my favourite Ruby author), and Metaprogramming Ruby by Paolo Perrotta (the two books complement each other very well), I felt I should rewrite SoftDeletableBase as an ‘Act as’ plugin.

The result was ActsAsSoftDeleteByField. A bit verbose, but as ActsAsSoftDeletable already existed I needed to differentiate my plugin from that. ActsAsSoftDeletable moves deleted items into another table, which was not been the functionality I wanted. My system uses a field in the model’s table to flag when a record is deleted. A simple solution, but ActsAsSoftDeletable maybe more suitable for many projects.

The two books gave me the knowledge I needed to understand how the methods used to create the mixin can be used. However, I found it very useful to look at other Acts As plugins such as acts_as_rateable, and acts_as_nested_set, to see how to arrange the code. The Ruby on Rails Guide was also useful.

Loading instance and class methods is actually fairly straight forward. Most of the work is done by this bit of code:

def self.included(base)
   base.send :extend, ClassMethods
 end

Getting the code to load properly was more difficult. It took me a little fiddling to get the init.rb file to work correctly. A lot of examples use class_eval here, but as I know the class names, I chose to use the simpler technique of monkey patching:

$:.unshift "#{File.dirname(__FILE__)}/lib"
require 'soft_delete_by_field'

class ActiveSupport::TestCase
  include ActsAsSoftDeleteByFieldAssertions
end

class ActiveRecord::Base
  include ActiveRecord::Acts::SoftDeleteByField
end

I used a set of assertions I’d used to test SoftDeleteableBase to test the new mixin, and included this code in the new plugin. That made it a lot easier to check the functionality. I created a new Rails app, and generated a Thing model. I then applied acts_as_soft_delete_by_field to thing, made sure it had a :deleted_at field, and ran the tests.

The next thing I did was to extend the functionality so that an alternative field could be used to store the deleted information. A few modifications and that was all working.

The last step was to create the gem. Russ Olsen’s book gave me the basics. The main thing that caused me problems was again initiating the script.

The main problem is that many of the examples on the web use the old system relying on /rails/init.rb, but I couldn’t get this to work. In the end, I realised that a file with the gem name was always loaded, and therefore that would be the place to put the hook script. So acts_as_soft_delete_by_field.rb was created and I put a hook script there. With that in place everything started working a treat.

The end result was the acts_as_soft_delete_by_field gem!

A Geek’s take on dealing with stress

May 9th, 2011

Being a CFR has put me in stressful situations. Trying to resusitate someone with kith and kin look on, is demanding.*

Last year I also started work carrying out bereavement support for a local hospice. The training involved in getting me up to speed in this work, has made me think a lot about how we behave in stressful situations such as bereavement.

Of course, I’m also a geek. Ruby programmer is my day job after all.

With all that in mind, here is my take on very stressful occurrences such as bereavement:

Bereavement: UDP and the unconcious mind

Your brain works very like a UDP stack, where the conscious mind sits at the application layer.

Most of the work is done within lower parts of the stack, and with everything working normally, stuff gets passed down into the unconscious brain and stuff pops back up without the top layer knowing or really caring about what happened lower down. You often think your conscious mind is doing all the work, but actually its all happening lower down.

Normally, the stack is able to handle problems and routes messages back and forth without any problem.

However, when something very stressful happens the stack gets disrupted. It gets information it doesn’t know how to handle. The result at the top layer is it doesn’t get any answers. Also as this is UDP, it doesn’t get any error messages either. So the net result is numb confusion.

With time the stack fixes itself. This can take hours or even days. Until then nothing computes properly. You can’t concentrate, you feel numb, and a little confused because you can’t figure out what is happening. These symptoms only go away once the stack fixes itself and normal conscious to sub-conscious communication returns.

This matches my experience:

Immediately after a very stressful situation I am left with a very numb, empty feeling where my brain just doesn’t work normally. The only thing that fixes this is time. I’ve learnt to recognise this feeling and the knowledge that time fixes it helps me deal with it. Trying to force my brain to fix the problem just makes the fix time longer.

Once the stack sorts itself out (for me, 2 to 12 hours is a common fix time), I can then start the rational process of sorting out the emotions and images that pop into my head.


* In fact, I find the reactions of relatives stick in my mind far longer than what actually happened to the patient or what I did. For example, the image of a wife crying at the bottom of the stairs is my main memory of a particular CPR attempt.

Model inhertiance

January 27th, 2011

I’m working on an application with some CMS features. One requirement is that new content is moderated before being published. To enable this, some users are allocated as moderators. To achieve this I have a moderator status column which can be either ‘some’ or ‘all’ (at the moment a ‘some’ moderator can only moderate content in some languages). Up until now it hasn’t be too cumbersome to have user methods associated with moderaters defined within the User class, but now I’m getting to the point where it would be good to split some of this functionality out into a separate class.

My problem was how to connect a new Moderator class to the User class.

A starting point is that I want Moderator class to inherit from User. That’s simple:

Moderator < User
end

The problem with this is if you do Moderator.find(:all) you get all users and not just those who are moderators.

In my last project, I overrode find, but that was a Rails 2 project and the same technique doesn’t work so well for this Rails 3 project. For example, Moderator.all still returns all users.

Another option would be to use ‘Single Table Inheritance’ (see ActiveRecord::Base api), but that would mean adding a new field and then limiting users to just one sub-class. For example, I think I will use the same technique with admins, and what if a moderator is both a moderator and an admin. Single Table Inheritance won’t let you do that.

In the end the solution was ridiculous simple. It is ‘default_scope’.

This works

class Moderator < User
  default_scope where("moderation_scope IN (?)", ['all', 'some'])
end

And this is what I ended up with:

class User < ActiveRecord::Base

  MODERATE_ALL_SCOPE = 'all'
  MODERATE_SOME_SCOPE = 'some'
  MODERATION_SCOPES = [MODERATE_ALL_SCOPE, MODERATE_SOME_SCOPE]

  def self.find_moderators
    where("moderation_scope IN (?)", MODERATION_SCOPES)
  end
end

class Moderator < User
  default_scope find_moderators
end

If I have special data entries that alter behaviour, I prefer to put them into constants and use the constants within the code. That way I can change the specific data entries at a later date without having to change every instance where it is used. Hence using MODERATION_SCOPES.

The final version also allows me to share the same code between User.find_moderators and Moderator.default_scope.

mongrel_service on Windows 7 64bit

October 25th, 2010

My current applications run on Linux in production, but I still develop on Windows PCs. My main works PC runs Windows 7 Pro 64bit. This isn’t too much of a problem. Just a couple of things don’t work (like wicked_pdf), but I can fire up a VirtualBox Linux image and test via that when I need to.

However, I needed to provide a production version of one of my applications for a colleague writing some documentation. In the past running a mongrel instance as a service on my PC has been great for this, but having recently upgraded to Rails 3, I’ve managed to kill my mongrel_service gem. Unfortunately reinstalling was not as easy as I thought. To get it to work I had to do the following:

Install win32-service separately and force it to install the binary version rather than build it from source. To do that:

gem install win32-service --platform x86-mswin32

Notice the double dash before platform. The blog where I first got this from had only one dash which caused me a little head scratching.

Then I had to install the ‘pre’ version of mongrel_service:

gem install mongrel_service --pre

I found that step from this blog.

BTW, I run a command prompt as the administrator when running gem commands (right click cmd icon and select ‘run as administrator’)

Once that was done I could use the mongrel_service as usual:

C:\Windows\system32>mongrel_rails service::install -N OLM_demo \ -c C:\web\public_site\olm -p 8001 -e production

Time format

October 7th, 2010

I found an interesting article by Todd Sayre on time formats in Rails. It is only short, but interesting. Based on that I created config/initializers/time_formats.rb in my latest app:

# Used to create time and datetime formatting short cuts. Search for to_formatted_s in the api
# Also see http://snippets.dzone.com/posts/show/2406

# If date = Time.local(2009,12,24,15,30,27)

Time::DATE_FORMATS[:datetime] = "%d-%b-%Y %H:%M"  # date.to_s(:datetime)  ---->  24-Dec-2009 15:30
Time::DATE_FORMATS[:date] = "%d-%b-%Y"            # date.to_s(:date)      ---->  24-Dec-2009
Time::DATE_FORMATS[:time] = "%H:%M"               # date.to_s(:time)      ---->  15:30
Time::DATE_FORMATS[:default] = Time::DATE_FORMATS[:datetime]   # Sets default behaviour for date.to_s

I think the code speaks for itself. As you can see it is very easy to extend Time#to_s to provide straight forward formatting. It is also easy to overwrite the default

Logging activity within a Rails application

May 27th, 2010

I wanted to add a tool to log users’ activity in my current application. I wanted something simple, and decided that the solution was to combine two techniques:

One: making session data available at the model and observer level. An article by Geoff Lane gave me the information I needed to be able to achieve that.

Two: use an observer to catch Model call backs and trigger an action in response. The Rails api documentation gave me the information I needed on creating an observer.

Here is a simple example as to how I was able to add an activity logger using these two techniques.

First I created a new module:

module MakeUserAvailableViaThread
  def user_in_thread
    Thread.current[:user]
  end

  def self.user_in_thread=(user)
    Thread.current[:user] = user
  end
end

This was based on Geoff Lane’s UserInfo module. I made two changes: I used a more descriptive module name; and I changed the method name because current_user was already used in the controller by my authentication system (‘restful_authentication’). The later stopped me logging in successfully until I spotted the problem.

I then added these two lines to my ApplicationController:

  include MakeUserAvailableViaThread
  before_filter :pass_current_user_to_thread_where_it_can_be_seen_by_observer

Together with this private method:

  def pass_current_user_to_thread_where_it_can_be_seen_by_observer
    MakeUserAvailableViaThread.user_in_thread = self.current_user
  end

So very similar to Geoff Lane’s code except with more descriptive method names.

I then needed to add the observer:

class ActivityLogger < ActiveRecord::Observer
  observe :account, :license
 
  include MakeUserAvailableViaThread

  def after_update(record)
    puts("HEY! something changed: #{user_in_thread.full_name if user_in_thread} altered #{record.class.to_s} #{record.id}")
  end

  def after_create(record)
    puts("HEY! something changed: #{user_in_thread.full_name if user_in_thread} created #{record.class.to_s} #{record.id}")
  end
end

However, nothing happened until I added this line to config/environment.rb:

config.active_record.observers = :activity_logger

Note that config.active_record.observers only gets called at application start, so you may need to stop and start your application before the observer starts working.

I now have a system I can extend to log activity. As shown above, only changes to accounts and licenses are logged, and the log just outputs to the console at the moment. However, now I have the mechanism, it is easy to create a new ActivityLog model and save the log entries to that in whatever format I fancy.

attachment_fu – working with database file storage

May 18th, 2010

Once I had attachment_fu working with files stored within the Rails application file system, I hit a problem as I wanted to be able to share files across three applications. The problem being that if the file was uploaded in one application, it would be stored within that application’s public folder. Without adding complication, this location wasn’t available to the other applications.

The solution was to change over to storing the files within the database. This took a couple of small modifications:

model
I changed the has_attachment declaration to:

has_attachment :max_size => 50.megabyte

The default attachment_fu is to use the database to store files. So removing the :storage entry in this statement was enough to change over from file system storage to database storage.

database
I has to add a new table and an additional column to my main model. The new table was created with:

    create_table :db_files do |t|
      t.column :data, :binary, :limit => 50.megabyte
    end

Note that adding a :limit entry can alter the blob field type created in the database. Without it the standard MySQL behaviour is to create an ordinary blob field. If the :limit statement indicated that a blob isn’t big enough, the data field will be set as a LONGBLOB.

The extra field added to my product_files table was ‘db_file_id’ which is an integer field.

public_filename
When working with database file storage, public_filename is no longer available. So I needed to come up with an alternative way to serve the file to the user.

controller download action
To do this I created a download action.

  def download
    if params[:id] and ProductFile.exists?(params[:id])
      product_file = ProductFile.find(params[:id])
      send_data(
        product_file.current_data,
        :type => product_file.content_type,
        :filename => product_file.filename
      )
    else
      flash[:error] = "Product file not found"
      redirect_to :action => 'index'
    end
  end

Note that send_data is a standard Rails method, so its use can be looked up in the Rails api. I wasted a little time trying to find this in the attachment_fu code.

helper
It was then just a case of creating a helper that pointed at this action.

  def link_to_download(product_file)
    link_to(
      'Download',
      :controller => 'product_files',
      :action => 'download',
      :id => product_file.id
    )
  end

view
This could then be used in a view, wherever I need a link to download a file I used it like this:

 <%= link_to_download(@product_file) -%>

Job done (except writing the tests of course)

Unit testing attachment_fu

May 14th, 2010

I’m working on a portion of my latest application that will need a facility to upload files. As these files are not images, I decided to use the plug-in attachment_fu. The thing that has caused me the most head scratching was how to set up unit tests to work with attachment_fu.

The class stores files related to a product. These are either code exerts or documentation. I’ve called the class ProductFile.

Params

If you are going to run tests that pass in data via a params hash, how do you get a file into the params in the right format. Here is the solution I worked out:

test_file_path = ActionController::TestCase.fixture_path + '/files/test.txt'
test_file = ActionController::TestUploadedFile.new(test_file_path)
@product_file_params = {
  product_id => 1,
  :document_type => 'document',
  :version => 2,
  :uploaded_data => test_file
}

I couldn’t get this to work without having the test file in a sub-folder of the fixtures folder. So I added a file ‘test/fixtures/files/test.txt’. Then I used ActionController::TestCase.fixture_path to determine the path.

Tear down

The other problem I had was that the standard Rails unit test tear down process wasn’t removing files created during the test. I overcame this by keeping track of each ProductFile created during the tests, and then using a teardown method to remove them all at the end of the test. This is the code that achieved that:

@@created_product_files = Array.new

def create_product_file_from_params(params_mod = {})
  product_file = ProductFile.create(@product_file_params.merge(params_mod))
  @@created_product_files << product_file
  return product_file
end

def teardown
  remove_product_files_created_during_test
end

def remove_product_files_created_during_test
  for product_file in @@created_product_files
    product_file.destroy if product_file.filename
  end
end

Now, as long as I used the create_product_file_from_params to create new product_files with params, the test would clean up after itself.

Fixtures

By the way, Product Files created via fixtures didn’t create a matching file in the file system. Which make it easier to keep things tidy, but needs to be kept in mind if you need an actual file to test against.

References

attachment_fu wiki

Mike Clark’s example of using attachment_fu

David Jones’ very interesting article on using attachment_fu with acts_as_versioned