Rails/Javascript programmer at Nedap

Posted by Bart ten Brinke Thu, 18 Dec 2008 22:45:33 GMT

Location: Groenlo, The Netherlands

URL: http://www.nedaphealthcare.com

Nedap Healthcare, market leader in the dutch home healthcare sector, is looking for a skilled and motivated web developer with a knack for interaction design. We provide an inspiring work environment with a mixture of coding and direct contact with our customers.

Even though Nedap is a fairly large company we work in small teams. Should you choose to accept, you will become the fourth member of our Moves team. Moves is a two year old web application that is sold to home healthcare organizations in combination with a 24" iMac. It allows planners to create routes that make the client, nurse and managers happy. If you want some more info about what we build and how we think, check our blog (listed below).

As a developer you should be proficient in HTML/CSS/Javascript and Ruby on Rails. Flash is a bonus, just like photoshop skills. Working in the healthcare business, we aim to develop most of our code using a BDD methodology.

We are based in Groenlo, a small dutch town near the german border. Though we are not necessarily looking for an on site developer we do prefer someone who is able to drop by from time to time regularly. Freelance is an option if you prefer.

We are offering a great job and unique company culture. It is important to us to build an excellent product by cherry-picking great people, not by bloating our team.

To apply If you are interested send your resume to andre.foeken@nedap.com

Posted in , ,  | Tags , , , ,  | no comments

RoR Workshop - 26 nov 2008

Posted by Andre Foeken Wed, 26 Nov 2008 18:58:47 GMT

This afternoon we held our first Ruby on Rails Workshop at Twente University. We got 20 Apple MacBooks together and allowed 25 people to bask in the glory of Rails!

We want to thank everyone who attended for their enthousiasm and energy. We had a great time! Also great thanks to Pragmatic Programmer for giving us a good deal on their latest Rails book and Inter-Actief (Michel) for their organisational skills.

Below are the sheets we used, courtesy of SlideShare.

Nedap Rails Workshop
View SlideShare presentation or Upload your own. (tags: nedap rails)

Posted in , ,  | Tags , ,  | 4 comments

Simple Net::Http stubbing / mocking

Posted by Andre Foeken Wed, 03 Sep 2008 07:02:07 GMT

Recently I've been implementing a simple web-service protocol that used Net::Http instead of ActiveResource magic. Although it was easy to mock ActiveResource objects, I found it hard to find any intel on how to mock actual Net::Http calls.

Below is a very basic example (which you can easily expand to fit your needs) of how to mock your calls. The example below shows a simple snippet that results in all 'posts' to be result in a Net::HttpSuccess object with a given XML body (which you can define)

Now define the XML data as follows:

Net::HTTP::xml_data = nil

Posted in ,  | Tags ,  | no comments

Rails Request log analyzer

Posted by Bart ten Brinke Thu, 14 Aug 2008 21:06:12 GMT

You've probably all been there: your application is running slow, but why? What views or actions are clogging up the mongrels? Or are the mongrels just waiting for the database?

Request log analyzer is a simple but very powerful command-line analysis tool to quickly determine what is taking time, on all kinds of different levels. At the moment it can tell you the following statistics:

  • Top 10 most requested actions
  • Top 10 actions by time - cumulative
  • Top 10 actions by time - per request mean
  • Top 10 worst DB offenders - cumulative time
  • Top 10 worst DB offenders - mean time
  • Mongrel process blockers (> 1.0 seconds) - frequency
  • Requests graph - requests per hour

For an example run, or the analyzer take a look at the github. http://github.com/wvanbergen/request-log-analyzer/

To install, run:

sudo gem install wvanbergen-request-log-analyzer --source http://gems.github.com

Posted in ,  | Tags , , ,  | 4 comments

Background processing with WorkerQueue

Posted by Bart ten Brinke Wed, 13 Aug 2008 19:25:48 GMT

Yes, I know there are a lot of background runners available for rails (I tried most of them), and they all seemed to have their downsides:

  • BackgroundRB -> Major memory leaks when performing large tasks and bloaty.
  • Spawn -> I really do not want to fork on every request. I use merb for that.
  • Starling -> Memcache and only does sequential processing.
  • ActiveMessaging -> Round hole Square peg.

Also non of these can handle big file uploads nicely and reliable. That is when I decided to create my own: WorkerQueue.

Main features:

  • Simple
  • Fast
  • Works via a rake task and prefers cron
  • Can handle large amounts of data
  • Sequential and Parallel execution on demand
  • Simple error reporting
  • Offload tasks to other or multiple machines

You can clone a copy here:

  git clone git://github.com/barttenbrinke/worker_queue.git vendor/plugins/worker_queue

Or visit github.

UPDATE: WorkerQueue 1.0 Stable is now available on Github.

Posted in  | Tags , , ,  | 2 comments

Nested include has major memory leak (Rails 2.0.1).

Posted by Bart ten Brinke Wed, 02 Jul 2008 14:00:33 GMT

As our mongrels were using up quite a lot of memory, so I tried to figure out what was causing this.

When running the app locally I found out that one certain page caused the mongrel to grow from 60 to 190 megabytes. A whopping 130 megabytes!

After commenting out some of the code, I realized that a single line was causing all of the memory usage

contracts = Contract.find( :all, 
  :conditions => ['contracts.employee_id IN (?) ', employees ],
  :include => [:expertise_profile => :qualifications ] )

Ouch! The nested include of rails somehow leaks a large amount of memory. The fix was a piece of cake.

contracts = Contract.find( :all, 
  :conditions => ['contracts.employee_id IN (?) ', employees ],
  :include => :expertise_profile )

Now my mongrel stays at 60 megabytes. I don't know if this issue persists in the new 2.1 Rails, but I'll check that soon!

Posted in  | Tags , , , ,  | 4 comments

Campfire Notifier for cruisecontrol.rb

Posted by Andre Foeken Thu, 17 Apr 2008 11:39:36 GMT

We added a campfire notifier to our build of cruisecontrol. Click on the link to download the builder plugin. It uses tinder as an API.

Posted in  | 2 comments

Optimizing math

Posted by Andre Foeken Thu, 10 Apr 2008 21:19:19 GMT

As you might have guessed from Bart's previous article we've been looking at ways to speed up our Rails app. We've been profiling and query optimizing but at some point we reached a dead end.

Our app needs to calculate a lot of distances between geo locations. Until now we've been happy using a home-grown Ruby method to calculate these distances but our profiling showed that it was (as one may suspect) horribly slow.

We now have several options:

  • We could try to built a faster Ruby method (but that would be hard since it's pure math and not really a lot can be done here)

  • We could use the database (mysql in our case) to calculate our distances (A lot more db connections in our case, since we need distances between lots of points. Not the standard stuff that gems like acts_as_mappable can handle)

  • Use RubyInline to create a faster C based method

We decided to look at RubyInline. A gem that enabled C code to be used right inside a Ruby script. We rewrote the method in C. A simple benchmark proved that our inline C method was 2.3 times faster!

require 'inline'
inline do |builder|
    builder.include '<math.h>'
    builder.c "double calc_distance_between(...) { ... }"
end

Although this result is very good, it does complicate your app and makes it less readable. These inline methods have to be used with care. But in our simple (and very localized) case we decided to keep the C method in favor of the pure Ruby call.

Posted in ,  | Tags , , , , ,  | 1 comment

Optimizing the queries of your rails app

Posted by Bart ten Brinke Wed, 09 Apr 2008 19:51:20 GMT

When you are developing your application, you should allways look for the following line in your development console.

Processing EmployeesController#index[GET]
Employee Load (0.055003) 
SELECT * FROM `people` WHERE `people`.`type` = 'Employee'

 select_type | key_len | type | Extra       |
---------------------------------------------  =>
 SIMPLE      |         | ALL  | Using where |

| id | possible_keys | rows | table  | ref | key
--------------------------------------------------
| 1  |               | 6965 | people |     |

The type ALL means that you are preforming a full table scan in a query. This is usually not a problem when you are in development mode, but what is you have millions of people in your database?

Usually it is pretty straight forward to find out where you were calling this from, as you will probably remember what the request was you did. If you are having a hard time, install the query_trace plugin. This gives the following result:

vendor/plugins/query_analyzer/lib/query_analyzer.rb:38:in `select'
app/controllers/employees_controller.rb:71:in `find'
app/controllers/employees_controller.rb:71:in `index'
vendor/plugins/browser-prof/lib/browser-prof.rb:32:in `process'

Looking at line 71 of the employees controller is a good idea here as you might be doing something stupid. As line 71 just reads: @employees = Employee.find(:all)) we have to turn to your database.

mysql -u root --database myapp_development

mysql> EXPLAIN SELECT * FROM `people` WHERE `people`.`type` = 'Employee';
+----+-------------+--------+------+------------------+
| id | select_type | table  | type | possible_keys    |
+----+-------------+--------+------+------------------+ =>
|  1 | SIMPLE      | people | ALL  |                  |
+----+-------------+--------+------+------------------+

+------+---------+------+------+-------------+
| key  | key_len | ref  | rows | Extra       |
+------+---------+------+------+-------------+
| NULL | NULL    | NULL | 6873 | Using where |
+---------+------+------+------+-------------+
1 row in set (0.00 sec)

As you can see we are not hitting any indexes. Lets try adding an index.

mysql> create index people_type_test on people (type);
Query OK, 6715 rows affected (1.38 sec)
Records: 6715  Duplicates: 0  Warnings: 0

Now we run the explain again:

mysql> EXPLAIN SELECT * FROM `people` WHERE `people`.`type` = 'Employee' ;
+----+-------------+--------+------+------------------+
| id | select_type | table  | type | possible_keys    |
+----+-------------+--------+------+------------------+ =>
|  1 | SIMPLE      | people |range | people_type_test |
+----+-------------+--------+------+------------------+

+------------------+---------+-------+------+-------------+
| key              | key_len | ref   | rows | Extra       |
+------------------+---------+-------+------+-------------+
| people_type_test | 768     | const | 2496 | Using where |
+------------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

Thats more like it, now we need to add this to our app trough a migration.

class CreatePeopleIndices < ActiveRecord::Migration
  def self.up
    add_index :people, :type
  end

  def self.down
    remove_index :people, :type    
  end
end

After a db:migrate and a restart of the server, we now see the following in the development console:

Employee Load (0.027666)
SELECT * FROM `people` WHERE `people`.`type` = 'Employee'
Analyzing Employee Load

 select_type | key_len | type | Extra       |
---------------------------------------------  =>
 SIMPLE      | 768     | ref  | Using where |

| id | possible_keys        | rows | table  | ref   | key
----------------------------------------------------------------------
| 1  | index_people_on_type | 2496 | people | const | people_type_test

Success! Also note that the load on the database has been cut in half.

Posted in  | Tags , , , ,  | 2 comments

Gettextgenerators update

Posted by Bart ten Brinke Mon, 31 Mar 2008 18:29:05 GMT

Gettext generators for rails 2.0 is out. It was available from the trunk for a long time, but now it was actually tagged. Note that it should work with the latest Gettext (1.90), but I have not yet tested this myself.

Posted in  | no comments

Older posts: 1 2 3 ... 5