mongrel_service on Windows 7 64bit

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
Posted in Ruby | Comments Off on mongrel_service on Windows 7 64bit

Time format

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

Update

Note that the previous format only affected Time objects. Date object text formats have to be defined separately. However, if you want the two to share a common format, this is a useful technique:

date_formats = {
  concise: '%d-%b-%Y' # 13-Jan-2014
}

Time::DATE_FORMATS.merge! date_formats
Date::DATE_FORMATS.merge! date_formats
Posted in Ruby | Comments Off on Time format

Logging activity within a Rails application

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.

Posted in Ruby | Comments Off on Logging activity within a Rails application

attachment_fu – working with database file storage

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)

Posted in Ruby | Comments Off on attachment_fu – working with database file storage

Unit testing attachment_fu

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

Posted in Ruby | Comments Off on Unit testing attachment_fu

ActiveRecord MS SQL adapter error fixed

It looks like the SQL Server adapter error I mentioned previously has been fixed.

The fix was posted yesterday (21-Apr-10).

Posted in Ruby | Comments Off on ActiveRecord MS SQL adapter error fixed

Test driven development is essential

After almost a year of using test driven development, I am now a total convert. I now feel it is so vital to good development practice that, across the board, I think I can label my previous applications as bad just because they don’t have rigorously tested tests. I was a sinner, but I have seen the light.

I’ve just had a good example of why test driven development is so important.

I have created a dynamic test method system that allows me write functional tests a little quicker. For example, one of the methods is “assert_item_passed_to_template”. I use method_missing to catch methods that match the method name pattern but replace ‘item’ with the name of the item they want tested. So assert_user_passed_to_template looks for a variable @user and matches it to the contents of assigns(:user), returning true if they match, and an error that describes the mismatch if they don’t.

One of the methods I use a lot was called assert_populated_item_passed_to_template. This didn’t match @user against assigns(:user) but instead matched assigns(:user) to @user_params (which is in effect params[:user]). So useful to make sure that the object returned to a failed save still contains the entered data.

However, I’ve been working on another part of the application for a week or two and have now returned to add some more edit functions. And I found the key world ‘populated’ confused me. I tried to use assert_populated_user_passed_to_template where I should have been using assert_user_passed_to_template. It took me a few minutes to work out why my my tests were failing. Populated is the wrong word. A @user object generated from the database is ‘populated’. I realised that if I was confused by populated (and I created the method name) so would anyone else reading my code.

However, every new and edit method in my application was tested with an assert_populated_item_passed_to_template call. What’s worse, because of the dynamic use of this method, I could not just rename the method; I had to rename all the methods with that pattern.

In the past that would have been a no, no. Just too much work to make sure the change hadn’t broken other parts of the application.

However, with this application I have tested from the start, so it was a straight forward task. I simply did a cross project replace of ‘assert_populated_’ with ‘assert_params_loaded_’ so that the method became ‘assert_params_loaded_item_passed_to_template’. Then ran all my tests. As they all passed, I could be sure the change hadn’t had any adverse knock on effects.

This means when I identify a way of improving my application, I feel much safer implementing that change than I did before I unit tested. So my application gets better as I work on it.

If you don’t test as you code, you don’t get a reliable set of tests that you know work, and you don’t get this vital safety net. Test driven development is up there with having source control, as vital prerequisites to good coding practice in my opinion. You don’t have to do it, but if you don’t you’ll regret it later.

Posted in Ruby | Comments Off on Test driven development is essential

Self referencing objects

My application has products, and each product can have components which are themselves products. I achieve this via a pair of self-referencing has_and_belongs_to_many relationships.

  has_and_belongs_to_many :components,
    :class_name => 'Product',
    :join_table => "product_grouping",
    :association_foreign_key => "component_product_id",
    :foreign_key => "group_product_id"

  has_and_belongs_to_many :groups,
    :class_name => 'Product',
    :join_table => "product_grouping",
    :association_foreign_key => "group_product_id",
    :foreign_key => "component_product_id"

Note the presence of the join table product_grouping which has two fields: group_product_id and component_product_id

I wanted to be able to collect together all components within a product hierarchy. So if my products are car, engine and piston: piston is a component of engine, which is a component of car. However, car.components would only return engine. I needed a method that would traverse the whole component hierarchy.

I achieved this by using a method that referenced itself within a collect:

  def all_components
    components.collect{|c| [c] << c.all_components}.flatten.uniq
  end

I’ve seen this technique used before, but always had a little difficulty getting my head around it. I found that the key to getting it working was to make sure that the method always returned an array or nil.

Now:

  car.components -> [engine]
  car.all_components -> [engine, piston]

What effectively is happening with car.all_components is this:

  • we first call all_components on car.
  • it works through each component and returns that component plus what ever is returned by its all_components. So as there is only one component (engine) engine.all_components is called, its results are returned in an array with a copy of itself.
  • engine.all_components acts on its only component piston. So it returns piston and the results of piston.all_components
  • piston has no components, so piston.all_components returns nil and the process ends.
  • flatten then gets rid of any array within array issues.
  • uniq tidies up instances where two products may share the same component.
Posted in Ruby | Comments Off on Self referencing objects

Test driven development

I’m starting to get into test driven development.

Test driven development has been advocated in the Rails community for some time (its core to the “Agile” coding methodology) but to be honest I’ve not bothered with it much. I am guilty of getting some code out to hit a deadline and looking to worry about writing the unit tests later. Of course, in the Rails community, that tantamount to admission of a most heinous crime. However, I’m currently reading this: “Clean Code” by Robert Martin and I’ve been persuaded by it to look at test driven development again, and I’m finding it really useful.

Basically the concept is that you write the unit test code first and then write code that satisfies the test. So before you write a new method, you write the code that tests the method’s functionality.

One of the key things the book advocates is that you make sure the test does not work before you start to write the object code. That sounds a little silly perhaps, but I’m finding it helps me make sure the object is working how I expect it to before I start adding code. It gives me a starting point. Then if I add code and the test fails, I know if that is the same failure I got originally or something has changed. It also ensures that I’m not just hitting a pre-existing fault.

By far the greatest benefit is that you know your unit tests work, because you are using them all the time. That makes refactoring less daunting, which supports the concept of reviewing and improving item names, and simplifying code, to make your code more readable and therefore easier to manage. The idea being that your first coding attempt will not be as good as your second or third itteration, so you need to be able to refactor easily to improve the code as you use is.

I’m also finding that I’m being more structured in my testing. When I create a new object or functionality I used to fire up a console and play with the object there. That meant that those tests were not saved. Now I user my unit test which means that each “good test” I use gets written into the unit test and I can use it again. Also if I find a bug, I write the test that replicates the bug before I fix it. That means my unit test gets better as the bug probably indicates that I’d missed something in my test. Then I feel more confident that I’ll be able to catch the reappearance of the bug if such a thing happens or be able to spot a related bug earlier.

Anyway, I thought you may find my ramblings of interest. If you fancy a read, I do recommend “Clean Code” by Robert Martin. He’s a Java programmer, so most of the examples use Java. However, my Java experience is very limited and I have still found it a very interest read.

—–
Update. I’ve just had a great example of why running the test to make sure it fails before you write the code is important:

I wrote a new test method and ran it, but got a pass! When I checked the new test method, I realised I’d forgotten the ‘test_’ prefix to the method name – so the test wasn’t being run with a normal test. That could have been difficult to spot after I wrote the object code because the test result would have been a pass!

Posted in Ruby | Comments Off on Test driven development

Bug in the activerecord-sqlserver-adapter-2.2.21 gem

There is a bug in the activerecord-sqlserver-adapter-2.2.21 gem.

The error is in the file:

\lib\active_record\connection_adapters\sqlserver_adapter.rb

Line 1058 reads:

FROM #{db_name}INFORMATION_SCHEMA.COLUMNS columns

But should read

FROM #{db_name}.INFORMATION_SCHEMA.COLUMNS columns

The lack of a full stop between the db_name and INFORMATION_SCHEMA causes an error because the database name gets appended to INFORMATION_SCHEMA and you get an error. For example, if the database was ‘db_one’ you’d get the error:

Invalid object name 'db_oneINFORMATION_SCHEMA.COLUMNS'

When you try a connection.select (e.g. connection.select_all(sql))

An update
There could be an issue with the simple solution of just adding a period. The issue is that if a db_name isn’t speciftied the SQL code could need to be just:

FROM INFORMATION_SCHEMA.COLUMNS columns

Therefore add a private method to sqlserver_adapter.rb:

def db_name_with_period(db_name)
  "#{db_name}."
end

And then update the problem line to:

FROM #{db_name_with_period(db_name) if db_name}INFORMATION_SCHEMA.COLUMNS columns

The problem has been posted to github:

http://github.com/rails-sqlserver/2000-2005-adapter/issues/closed/#issue/3

update 15-Jan-10
The problem is still present in the latest version of the adapter and therefore I have added a new issue.

Posted in Ruby | Comments Off on Bug in the activerecord-sqlserver-adapter-2.2.21 gem