A few weeks ago I needed a Rake task to answer a simple question for me:
“What’s my name?”
I honestly can’t quite remember why exactly the task needed to know it’s own name, but at the time it seemed important and I spent a couple hours digging about before I found out that Rake tasks are shy by nature. Or at least when implemented the way almost every tutorial tells you to implement them:
namespace :life do
desc "The answer to life, the universe, and everything"
task :answer do
puts "The answer to life, the universe, and everything is 42."
end
end
But how do I know what the name of the current task is? Well, after making a couple of random attempts (like “puts task.name”) and digging around in the very sparse documentation on the Rake homepage, I stumbled across a bit of documentation that talked about “Tasks with Actions”:
Actions are defined by passing a block to the task method. Any Ruby code can be placed in the block. The block may reference the task object via the block parameter.
task :name => [:prereq1, :prereq2] do |t|
# actions (may reference t)
end
Ah ha! “The block may reference the task object via the block parameter.” That’s exactly what I was looking for. Adding the block parameter allows us to reference the task object itself. And the task object itself has a good bit of useful meta information:
namespace :life do
desc "The answer to life, the universe, and everything"
task :answer do |t|
puts t.name
puts t.comment
puts t.scope
end
end
The task now returns the following:
life:answer
The answer to life, the universe, and everything
life
The first line of output is nifty, and answers the “What’s my name?” question with the fully scoped name of the task. Given that much it’s probably not hard to return the task name in even the most deeply namespaced Rakefile. The second line is the “comment” — actually the description of the task. And the third line gets us the scope (namespaces). There are more methods available, but check teh googles for “Rake::Task api”.
So with this meta information we can do something useful like:
namespace :life do
desc "The answer to life, the universe, and everything"
task :answer do |t|
puts "#{t.comment} is 42."
end
end
Voila. And that’s probably enough meta for one day.
Posted: November 14th, 2009 by Neal Enssle
Tags: code, howto, programming, rake, ruby, tools
No Comments »
I keep forgetting this snippet, and then spend hours re-discovering/re-inventing it. So for the record: Here’s a bit of magic to let you filter your Subversion (SVN) logs by date and author:
svn log -vr {20091014}:"HEAD" | sed -n "/nealenssle/,/-----$/ p"
I use it in a bash shell script function that I’ve got in my .bash_profile script like so:
function svnlog {
svn log -vr {$1}:"HEAD" | sed -n "/$2/,/-----$/ p"
}
And then call it like so:
svnlog 20091014 nealenssle
Happy spelunking!
Posted: October 14th, 2009 by Neal Enssle
Tags: code, programming, scm, subversion, tools
No Comments »
The idea I’m exploring here is whether or not we can build a CMS (content management system) in Ruby on Rails that can dynamically build a CMS. In other words, can we write Rails code that writes Rails code.
It seems we can. This is pretty awesome, and somewhat frightening, because it apparently works. Here’s a method in, say, a “utils_controller.rb”:
def generate_scaffold
@results = `script/generate scaffold
Things name:string value:string`
end
Note the use of backticks around the shell commands to generate a scaffold. If you run that method in your browser, it actually generates the controller, model, migration, etc.
Then do this:
def migrate
@results = `rake db:migrate`
end
Yep. Now you just migrated the database and have new “things” table.
Eureka?
Obviously some issues here (like… OMGWTF! Run away! Do not try this at home!). But I’m a little bit excited…
Posted: October 10th, 2008 by Neal Enssle
Tags: code, howto, programming, rails
No Comments »
Here’s a function to turn any given string into a CamelCase “WikiWord” in Ruby:
def wikify(phrase)
phrase.gsub!(/^[a-z]|\s+[a-z]/) { |a| a.upcase }
phrase.gsub!(/\s/, '')
return phrase
end
Voila. This turns “my dog has fleas” into “MyDogHasFleas”.
Note: I’m sure there’s a way to fix this so that it’s just one regular expression? Feel free to chime in!
Posted: July 21st, 2007 by Neal Enssle
Tags: code, howto, programming, rails
6 Comments »
Here’s the situation: You have two SELECT elements on a form. When the user chooses an item out of the first SELECT element, the contents of the second SELECT element need to change and show different values based on the initial selection.
This used to take quite a bit of JavaScript wizardry. But it’s pretty straightforward in Rails using a bit of Ajax. Here’s how:
First, make sure you’re including the Ajax libraries (Prototype, script.aculo.us, etc.) in your layout like so:
<html>
<head>
<%= javascript_include_tag :defaults %>
</head>
<body>
...
Next, create a form with your initial SELECT, and empty second SELECT, and set up field observer. Here’s a really simple example:
<form>
<select id="states" name="states">
<option value="0"></option>
<option value="1">Colorado</option>
<option value="2">Illinois</option>
<option value="3">Wyoming</option>
</select>
<%= observe_field "states", :update => "cities",
:with => "city_id", :url => { :controller => "test",
:action => "get_cities" } %>
<br />
<select id="cities" name="cities">
<option></option>
</select>
</form>
Finally, you’ll need to set up a method to handle the call from the observer and a corresponding view page to generate the HTML content that will replace everything betwen the SELECT tags in the second SELECT. Here’s an example "get_cities" controller:
def get_cities
@cities = City.find_by_state(:all)
end
And an example "get_cities.rhtml" file:
<% for city in @cities %>
<option value="<%= city.id %>"><%= city.name %></option>
<% end %>
And there you go. This much should dynamically update the "cities" SELECT element with new content every time the "onchange" event is fired on the initial "states" SELECT form element.
Posted: April 12th, 2007 by Neal Enssle
Tags: ajax, code, howto, programming, rails
24 Comments »
We’re just starting to get into Ruby on Rails at my work, and we’re close to deploying our first application to a production server with Capistrano.
Capistrano makes it easy for developers to deploy code to the production server from their own workstations. But we quickly ran into two problems:
- It’s often the case that a developer’s username on their local workstation is different from their username on the production server. This requires you to set the developer’s server username in the “deploy.rb” file. Hard-coded.
- Hard-coding a single username makes it difficult for multiple users to share a “deploy.rb” file.
Well, it turns out that Capistrano is better than all that. With a little bit of conditional logic and the ability for Cap to read environment variables, the problem is solved like this in the “deploy.rb” file:
if ENV["USER"] == "robert"
set :user, "bob"
elsif ENV["USER"] == "elizabeth"
set :user, "beth"
end
Voila.
Posted: April 11th, 2007 by Neal Enssle
Tags: code, howto, programming, rails, tools
No Comments »
A little while ago I decided I needed to get my head around this whole “Ajax” thing. From Wikipedia:
Ajax, shorthand for Asynchronous JavaScript and XML, is a web development technique for creating interactive web applications. The intent is to make web pages feel more responsive by exchanging small amounts of data with the server behind the scenes, so that the entire web page does not have to be reloaded each time the user makes a change. This is meant to increase the web page’s interactivity, speed, and usability.
Mainly it was for a couple of issues we were having at work, but I’ve long been a fan of the “magic” behind sites like Amazon, Flickr, and 30boxes.
So, after quite a bit of searching around in books and blogs, I managed to cobble together a couple of extremely simple scripts that take most of the mystique out of Ajax.
In fact, we’re also taking the “x” (for XML) out of Ajax, since this routine works by having your page call a JavaScript function that passes a request to some server-side code which then returns pure HTML. This HTML gets inserted into a container div on the calling page.
So here we go with the tutorial. An Ajax “how-to” in three easy steps (you can also download the code):
First things first, you need to get a “request object” that handles sending your request to the server. So we need a JavaScript function (inside a script block):
// initAjaxRequest():
// Create a request object, based on browser type:
function initAjaxRequest() {
var request;
if (window.ActiveXObject) {
request = new ActiveXObject("Microsoft.XMLHTTP");
} else {
request = new XMLHttpRequest();
}
return request;
}
Next, you’ll need to instantiate the request object at some point (this happens inside a JavaScript script block but outside of any function):
// Set a variable to hold an Ajax request object:
var ajaxRequest = initAjaxRequest();
Finally, you’ll need a JavaScript function that you can call to actually send the request to the server. The following function (inside a script block) takes URL parameter (that’s the server-side module, servlet, or page that will produce some HTML for us), along with a second parameter (“container”) that tells us where to put the resulting HTML:
// sendAjaxGetRequest(url, container):
// Send an asychronous request to a specific URL,
// designating CSS container ID to hold the
// response information (HTML).
function sendAjaxGetRequest(url, container) {
ajaxRequest.open('GET', url);
ajaxRequest.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
ajaxRequest.onreadystatechange = function() {
if (ajaxRequest.readyState == 4 &&
ajaxRequest.status == 200) {
document.getElementById(container).innerHTML =
ajaxRequest.responseText;
}
}
ajaxRequest.send(null);
}
Now, to actually use these JavaScript functions, all we need to do is:
1. Call the JavaScript sendAjaxGetRequest(url, container) function (perhaps via an “onclick” handler), specifying the URL of a page that “does something” on the server-side, and a “container”. For example:
<p onclick="sendAjaxGetRequest('doSomething.htm', 'responseDiv');">Do something!</p>
2. Make sure we have a “container” div on the calling page that will hold the resulting HTML. For example:
<div id="responseDiv"></div>
Note that “doing something” can be as simple as printing any HTML to the screen. For example, the “doSomething.htm” page could simply look like this:
<p>I did something!</p>
Of course, this target page could be far more complex, such as a PHP page, ColdFusion template, or Java servlet that updates a database. The point of Ajax is just that you’re now able to post a request to the server, do something, and get information back without having to refresh the page.
If you want to send form fields via a POST instead URL parameters via a GET, here’s a slightly different function:
function sendAjaxPostRequest(url, parameters, container) {
ajaxRequest.open('POST', url);
ajaxRequest.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
ajaxRequest.onreadystatechange = function() {
if (ajaxRequest.readyState == 4 &&
ajaxRequest.status == 200) {
document.getElementById(container).innerHTML =
ajaxRequest.responseText;
}
}
ajaxRequest.send(parameters);
}
This function takes a “parameters” argument, which can be an encoded string of form field parameters. For example:
var url = "doSomething.php";
var parameters = "myField=" +
encodeURI(document.myForm.myField.value);
sendAjaxPostRequest(url, parameters, "responseDiv");
That’s mostly it. Enjoy! (Again: You can download the code).
Posted: September 26th, 2006 by Neal Enssle
Tags: ajax, code, howto, programming
No Comments »