Here is a silly project that I knocked out last week - a generator of Fake Captain Beefheart Song Titles
It was inspired by a comment on Gideon Coe's radio show on BBC 6 Music where he wondered if such a thing existed - it didn't - so I wrote one!
The 'algorithm', if you can call it that, combines words from real Beefheart song titles and a list of others that sound (to me) like they could be. The structure of the real titles is relatively simple with most of them following a few simple patterns. Some of the generated titles don't work but every so often it'll spit out a good one.
The site is built with Ruby and Sinatra, with some jQuery thrown in for the scrolling effect. It serves as a nice example if you are learning Sinatra. You can find the code at Github and the application is hosted on Heroku.
It's just a bit of fun, but writing a small, self-contained application like this is a great way to learn new technologies. Giving yourself a short time frame in which to develop and deploy a complete application is a great exercise in efficiency.
A collection of computer systems and programming tips that you may find useful.
Brought to you by Craic Computing LLC, a bioinformatics consulting company.
Monday, November 14, 2011
Friday, November 11, 2011
When jQuery $.ajax() keeps returning the same value on Internet Explorer
I just mentioned this in my last post, but it is important enough that I'm going to give it its own post!
If you have jQuery Ajax calls, such as $.ajax() , $.get(), etc., that are continually fetching data from a remote server, you may find this works on Firefox, Chrome, etc. but in Internet Explorer it keeps returning the same value.
IE has cached the first return value and thinks that you are making identical requests so it just uses the cached value and never contacts the server.
Turn off caching by adding a call to ajaxSetup at the start of your script block and set cache to false.
<script>
$.ajaxSetup ({
cache: false
});
[...]
</script>
The fix is simple once you realize it but it took me a while to figure it out this morning.
Debugging JavaScript is painful at the best of times. It's worse when you throw AJAX into the mix. So take small steps and test on multiple platforms right from the start. I need to learn that lesson.
Updating a DIV with jQuery and Sinatra
Here is a minimal example of how to update a DIV in a web page with content from a remote Sinatra server using jQuery AJAX.
On the Server end you want an action that generates some new content and just returns it as a string. Let's just get the current time:
get '/update' do
Time.now.to_s
end
In the client web page you need to include the jQuery library:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
You need a named DIV that will receive the content
<div id='update-div'></div>
Then you need to create your script block. You need a function that updates the DIV. update_time() calls the jQuery get function with two arguments. The first is the URL of the server action. The second is a function that is called on the returned data and the third is a type of data that the server will return, which is 'text' in our case.
Here we update the named DIV with the string returned from the server. Then we use the setTimeout function to wait 5 seconds, and then we call the function itself to repeat the process. That instance fetches content from the server, waits 5 seconds, calls itself, and so on.
At the start of the script block we add a call to ajaxSetup and set cache to false. This seems to be necessary for Internet Explorer which would otherwise cache the first value returned and keep using that instead of fetching new values.
Finally we make the initial call to the function when the document is first loaded and ready.
<script>
$.ajaxSetup ({
cache: false
});
$(document).ready(function() { update_time(); });
// fetch text from the server, wait 5 secs and repeat
function update_time() {
$.get("/update",
function(data) {
$("#update-div").html(data);
window.setTimeout(update_time, 5000);
},
'text');
}
</script>
The jQuery get function is a simplified wrapper around the ajax call.
That is all you need to have a DIV continually updated with remote content, in this case coming from Sinatra.
On the Server end you want an action that generates some new content and just returns it as a string. Let's just get the current time:
get '/update' do
Time.now.to_s
end
In the client web page you need to include the jQuery library:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
You need a named DIV that will receive the content
<div id='update-div'></div>
Then you need to create your script block. You need a function that updates the DIV. update_time() calls the jQuery get function with two arguments. The first is the URL of the server action. The second is a function that is called on the returned data and the third is a type of data that the server will return, which is 'text' in our case.
Here we update the named DIV with the string returned from the server. Then we use the setTimeout function to wait 5 seconds, and then we call the function itself to repeat the process. That instance fetches content from the server, waits 5 seconds, calls itself, and so on.
At the start of the script block we add a call to ajaxSetup and set cache to false. This seems to be necessary for Internet Explorer which would otherwise cache the first value returned and keep using that instead of fetching new values.
Finally we make the initial call to the function when the document is first loaded and ready.
<script>
$.ajaxSetup ({
cache: false
});
$(document).ready(function() { update_time(); });
// fetch text from the server, wait 5 secs and repeat
function update_time() {
$.get("/update",
function(data) {
$("#update-div").html(data);
window.setTimeout(update_time, 5000);
},
'text');
}
</script>
The jQuery get function is a simplified wrapper around the ajax call.
That is all you need to have a DIV continually updated with remote content, in this case coming from Sinatra.
Latest version of jQuery on Google APIs
If a web page uses the jQuery library it usually makes sense to link to copy hosted on an external content delivery network (CDN). You don't have to keep an updated copy on your site, the client may already have this copy cached, and the CDN has high bandwidth connections. Google, Microsoft and jQuery themselves offer CDN hosted jQuery.
I use the Google version and call it with this line:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
That is fine, but what happens when a new version comes out?
In these cases some sites will offer a 'latest' url that automatically points to the most recent version.
Google does not do that - but they offer something similar, and which might be slightly better.
If I want version 1.7.0 and nothing else then I use the link given above.
If I want the latest version in the 1.7 series then I use:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
And if I want the latest version in the 1 series then I use:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
Note that you don't always want to use the most general form. New releases are not necessarily back compatible. But you have the choice.
And note that you no longer need to include type="text/javascript" in the script tag anymore - it's the default.
Thursday, November 10, 2011
Sorting on multiple String keys in Ruby
Ruby gives you two ways to sort arrays of 'complex' objects - sort and sort_by
Consider this array of hashes
array = [{:key0 => 'foo', :key1 => 'bar'},{:key0 => 'hot', :key1 => 'cold'}, ... ]
sort_by is the most compact form. To sort on :key0 in ascending order you write:
array.sort_by{ |a| a[:key0] }
sort is a little more verbose, but offers more flexibility:
array.sort{ |a, b| a[:key0] <=> b[:key0] }
If you want to sort strings in descending order then you switch the a and b assignments:
array.sort{ |a, b| b[:key0] <=> a[:key0] }
You can use sort_by with multiple keys if you include them in an array:
array.sort_by{ |a| [ a[:key0], a[:key1] }
But if you are using strings and you want one of the keys sorted in descending order then you need to use sort.
In this example the desired ordering is to first sort on :key0 in descending order and then on :key1 in ascending order:
array.sort do |a,b|
(b[:key0] <=> a[:key0]).nonzero? ||
(a[:key1] <=> b[:key1])
end
Not the most elegant or concise piece of code, but it does the job.
Consider this array of hashes
array = [{:key0 => 'foo', :key1 => 'bar'},{:key0 => 'hot', :key1 => 'cold'}, ... ]
sort_by is the most compact form. To sort on :key0 in ascending order you write:
array.sort_by{ |a| a[:key0] }
sort is a little more verbose, but offers more flexibility:
array.sort{ |a, b| a[:key0] <=> b[:key0] }
If you want to sort strings in descending order then you switch the a and b assignments:
array.sort{ |a, b| b[:key0] <=> a[:key0] }
array.sort_by{ |a| [ a[:key0], a[:key1] }
But if you are using strings and you want one of the keys sorted in descending order then you need to use sort.
In this example the desired ordering is to first sort on :key0 in descending order and then on :key1 in ascending order:
array.sort do |a,b|
(b[:key0] <=> a[:key0]).nonzero? ||
(a[:key1] <=> b[:key1])
end
Not the most elegant or concise piece of code, but it does the job.
Wednesday, November 9, 2011
Manipulating Model/Table/Controller Names in Rails
There are some very useful methods that operate on the names of your models, tables and controllers in Rails. I use them infrequently enough that I have to relearn them every time - so I'm putting them in here:
Given a string with the name of a model (e.g. Project), how can I create an ActiveRecord call on the fly using that model?
str = 'Project'
project = (str.constantize).find(1)
How can I get the name of the corresponding controller ?
controller = str.tableize
Given a string with the name of a controller, how can I get the name of the Class/Model ?
str = 'sales_contact'
model_name = str.camelize
I the string is plural:
str = 'sales_contacts'
model_name = str.classify
How do I do the reverse operation?
str = 'SalesContact'
name = str.underscore
Given a string with the name of a model (e.g. Project), how can I create an ActiveRecord call on the fly using that model?
str = 'Project'
project = (str.constantize).find(1)
How can I get the name of the corresponding controller ?
controller = str.tableize
Given a string with the name of a controller, how can I get the name of the Class/Model ?
str = 'sales_contact'
model_name = str.camelize
I the string is plural:
str = 'sales_contacts'
model_name = str.classify
How do I do the reverse operation?
str = 'SalesContact'
name = str.underscore
Parsing 96 / 384 well Plate Maps
In molecular biology and related fields, we use rectangular plastic plates with 96 or 384 wells for many purposes, allowing us to run many experiments in parallel. In particular, they are the standard format for tasks involving laboratory robotics, such as fluid dispensing, DNA sequencing, mass spectrometry, etc.
In setting up a plate of samples, it is common for a researcher to use Excel to create a 'plate map' - a table of 8 rows and 12 columns, for a 96 well plate, with each cell holding information on the sample in that well.
Converting this into a list of individual wells for input into an instrument or a piece of software should be straightforward but variability in manually created plate maps can be an issue. Extraneous text and the placement of the table in the spreadsheet are just two of them.
I have to deal with this problem every year or two and so I decided to write a utility script that implements this conversion and offers several options for the output file.
It is not intended as a complete solution for any one application. Rather it is a starting point that I can customize as needed.
I know other people have to deal with the same type of data, so I've made the script as general as possible and put it up on github under the MIT license. Please adapt this as you see fit for your needs.
The script can take CSV or Tab delimited files as input, containing 96 or 384 well plate maps. The output is a table with one well per row and the columns : plate, row, column, value. Options allow you to specify CSV or Tab delimited as the output format, whether to parse the input in row or column major order, and whether or not to output empty cells in the plate map.
The code is written in Ruby and you can find it at https://github.com/craic/plate_maps
Let me know if you find it useful
Subscribe to:
Posts (Atom)