Dreaming in Code

By Phil Matarese on April 21st, 2008

Tagged with: ruby, frivolity

I dreamed about Ruby again last night.  I was looking at the way code looked, and I realized that the results of executing the code looked like the code that was being executed.  It went on recursively with code that looked like code that looked like code...  There was even drop-shadows and reflection on the code - it was beautiful.

I'm not sure if this is a result of reading Why's (Poignant) Guide to Ruby or if I'm just wandering down the same path he did.  It doesn't really matter though, in fact, the only thing that matters now is creating Ascii Art numbers.  This is important, I must do this...

  1  class NumberWang
2 ALL = %w{ zero one two three four five six seven eight
nine
}
3
4 # Omphaloskepsis
5 def self.reveal_method(method_name = nil)
6 @@source ||= File.open(__FILE__).read
7
8 source = ''
9
10 if method_name
11 in_method = false
12 @@source.each do |s|
13 next unless in_method || s.strip == "def
self.#{method_name}
"
14 break if s.strip == "end"
15 in_method = true
16
17 source << s
18 end
19 else
20 ALL.each{|a| reveal_method(a)}
21 end
22
23 puts source.chop #drop the linebreak
24 puts
25 end
26
27 def self.all
28 ALL.map{|a| self.send(a.to_sym)}
29 end
30
31 def self.zero
32 ----------1*1-------------
33 ---------1 - 1------------
34 ---------1 * 1------------
35 ---------1 - 1------------
36 ----------1*1------------1
37 end
38
39 def self.one
40 ------------1--------------
41 -----------11--------------
42 ------------1--------------
43 ------------1--------------
44 ----------11-1-------------1
45 end
46
47 def self.two
48 ----------1-1--------------
49 -------------1-------------
50 -----------11--------------
51 ----------1----------------
52 ----------1-11------------1
53 end
54
55 def self.three
56 ----------1--1------------
57 --------------1-----------
58 -----------1-1------------
59 --------------1-----------
60 ----------1--1-----------1
61 end
62
63 def self.four
64 ----------1--1------------
65 ----------1--1------------
66 ----------1-1-1-----------
67 -------------1------------
68 -------------1------------1
69 end
70
71 def self.five
72 ----------11-1-------------
73 ----------1----------------
74 -----------1-1-------------
75 --------------1------------
76 -----------1-1------------1
77 end
78
79 def self.six
80 ----------11*1-------------
81 ---------1-----------------
82 ---------1*-1--------------
83 ---------1 - 1-------------
84 ----------1-1-------------1
85 end
86
87 def self.seven
88 ----------11-1-------------
89 -------------1-------------
90 ------------1--------------
91 -----------1---------------
92 ----------1---------------1
93 end
94
95 def self.eight
96 ----------11*1------------
97 ---------1 - 1------------
98 ----------1-1-------------
99 ---------1 - 1------------
100 ----------1-1-------------1
101 end
102
103 def self.nine
104 -----------1*1------------
105 ----------1 - 1-----------
106 -----------1*11-----------
107 -------------1------------
108 -----------1-------------1
109 end
110 end

Ok, that was a strange diversion.  Sorry if I've upset anyone.  I'll try to stay a little more focused from now on.

Wrapping Up

There's some fun stuff in there (apart from the numbers) that might be worth poking around in.  Specifically, the reveal_method, which I think is too much of a hack to be useful but was fun to play with nonetheless.  Now, load this thing in irb and have some fun exploring.

curl 'http://rubyforge.org/snippet/download.php?type=snippet&id=337' > number_wang.rb
irb -r number_wang.rb

Try something like this, NumberWang.reveal_method :two to get you started.

Ultimate One-Liner

By Phil Matarese on April 18th, 2008

Tagged with: dilbert, one-liner

Update - This post has fallen flat, now that you can subscribe to daily dilberts for free.

I love one-liners, and here's the command I use to read Dilbert everyday:

curl -s http://dilbert.com | grep -o -m1 -E '\/comics\/dilbert\/archive\/images\/dilbert[0-9]*\.(gif|jpg|jpeg)' | sed "s/\(.*\)/--url http:\/\/dilbert.com\1/" | curl -s --config - | open -f -a Preview.app

From now on, I expect you to finish all of your projects in one hour.Unlike other publications, I don't read dilbert.com for the articles.  I also don't read it for the advertisements or any of the other junk – I just want to see today's comic.  Only, the file for the daily comic has randomness in the filename which makes it complicated to automatically scrape the comic (I guess they want to avoid people doing what I'm doing... silly people).  Nothing is too complicated for a one-liner, though.

I aliased this script in my .bash_login file, so a fresh Dilbert is always just a few keystrokes away.  (Sorry, the Preview.app part makes it only work on Mac.  I guess you'd have to pipe it into a different app for other systems.)

Autotest with Growl. And iChat?

By Phil Matarese on April 18th, 2008

Tagged with: rails, autotest, growl, ichat

Autotest is Great

It adds another layer of satisfaction onto test-driven development.  The ideal setup for TDD is to have two monitors – one for developing and another for your autotest terminal (along with server and log-tailing terminals.)  Without a second monitor, though, your autotest results need a better way of notifying you.  Many people have solved this on their Macs by using Growl's growlnotify in a .autotest file (goes in your project root or home directory.)  It could be as simple as requiring ZenTest's own growl interface:

1  require 'autotest/growl'

But, for more control, it's sometimes better to expose the guts and operate a little bit like this:

 1  module Autotest::Growl
2 PICTURE_ROOT = '/Users/philip/Pictures/Autotest/'
3
4 def self.growl msg, status
5 pri = {:fail=>2,:pending=>-1,:ok=>-2}[status]
6 title =
{:fail=>'Failed',:pending=>'Pending',:ok=>'Passed'}[
status]
7
8 msg.gsub!("\n","\\\n\n")
9 system "growlnotify -n autotest --image
\"#{PICTURE_ROOT}rails_#{status.to_s}.png\" -p
#{pri} -m \"#{msg}\" \"Tests #{title}\"
"
10 end
11
12 def self.failure_details results
13 details = ''
14 results.each do |line|
15 line = line[/[^\/]*\.rb\:[0-9]*\:/]
16 details += "#{line}\n" if line
17 end
18 return details
19 end
20
21 def self.pending_details results
22 results.slice!(0,3)
23 results.slice!(-4,4)
24 details = ''
25 results.each do |line|
26 details += "#{line[/[^\(]*/]}\n"
27 end
28 return details
29 end
30
31 Autotest.add_hook :ran_command do |at|
32 output =
at.results.last[/[0-9]*\sexample(s)*,\s[0-9]*\sfailu
re(s)*(,\s[0-9]*\spending)*
/]
33 if output =~ /\s0\sfailure(s)*/
34 if output =~ /\spending*/
35 growl "#{pending_details(at.results)}\n#{output}",
:pending
36 else
37 growl "#{output}", :ok
38 end
39 else
40 growl "#{failure_details(at.results)}\n#{output}",
:fail
41 end
42 end
43 end

Growl SettingsThat script is based on internautdesign.com's, and uses their images (rails_fail.png, rails_ok.png).  I added a few updates, like better formatting in the Growl notification and implementation of 'pending' status (rails_pending.png).  It took me a few tries to get the line-breaks right in the notification, until I realized that I needed double backslashes – one for the shell, and one for the \n.  I also decided to grab a little more than the last line of results for pending and fail statuses, which took a few ugly lines of text hacking.  Also, you should set your Growl colors to something like the picture on the right.

That Was Nice

That was nice, and it solves the single-screen-notification problem pretty well, but now it's time for something new.

Bragging about my ruby-centric iTunes playlist through iChat.Test failures publicized through iChatAnd, since I was looking for a reason to try out RubyOSA, I wrote a .autotest script that notifies my team (and my friends (and my mom)) whenever a test passes (or fails (or is pending)) via iChat's status and buddy icon.  Too fun!  Maybe this isn't the most practical way to do TDD, but it's fun code to play with.  You could even use RubyOSA to lower the volume on iTunes whenever there are too many errors – maybe.

 1  require 'rbosa'
2
3 module Autotest::Chat
4 PICTURE_ROOT = '/Users/philip/Pictures/Autotest/'
5
6 def self.chat test_stats, status
7 @@chat ||= OSA.app('iChat')
8 begin
9 @@chat.status_message = test_stats
10 @@chat.status = status==:fail ? 'away' : 'aval'
11 @@chat.image =
File.read("#{PICTURE_ROOT}rails_#{status.to_s}.png
")
12 rescue
13 #ignore it, iChat is prolly just turned off
14 end
15 end
16
17 Autotest.add_hook :ran_command do |at|
18 output =
at.results.last[/[0-9]*\sexample(s)*,\s[0-9]*\sfailu
re(s)*(,\s[0-9]*\spending)*
/]
19 if output =~ /\s0\sfailure(s)*/
20 if output =~ /\spending*/
21 chat output, :pending
22 else
23 chat output, :ok
24 end
25 else
26 chat output, :fail
27 end
28 end
29
30 Autotest.add_hook :quit do |at|
31 chat "Chillin'", :chillin
32 end
33 end

Autotest has some usefel hooks like 'quit', so I can let people now that I'm chillin' again (rails_chillin.png) after a successful round of testing.  Oh, and you can get the chat code from RubyForge with the following command.

curl 'http://rubyforge.org/snippet/download.php?type=snippet&id=329'

Today

As I wrote this post, I started looking deep into the bowels of ZenTest to make sure I was setting up my autotest scripts correctly.  What I found was heaps of code already designed to use Growl, and iChat, and KDE Notify, Snarl, Heckle, and some other stuff.  What I didn't find was much documentation about the features – you pretty much have to dig into the source.  And even with the source, some of the code's usage is mysterious – like utilizing generic autotest hooks by adding require 'autotest/growl' or require 'autotest/shame' to an empty .autotest file.

Now Back To the RUBY-CENTRIC Music

More iTunes playlist nonsense

Using Foxy Fixtures for Polymorphic Associations in Rails 2

By Scott Roth on April 5th, 2008

Tagged with: rails, rails 2.x, fixtures, polymorphic associations

As we all know, the Rathole plugin was sucked into Rails core with the release of Rails 2 and now using fixtures has become, um, foxier.  One use case that wasn't immediately clear to me was how to specify polymorphic relationships using the new and improved syntax.  It turns out that this is straightforward.

Let's say your application captures contact information for several models.  Our hypothetical application is a brand new social network for people in the music industry.  (Quick, let's pitch it to VCs!)  Each application user would have contact information and, since they are in the music industry, they belong to a Record Label.  Record Labels also have contact information stored for them.  So we get this:

 1  class Contact < ActiveRecord::Base
2 belongs_to :contactable, :polymorphic => true
3 end
4
5 class User < ActiveRecord::Base
6 has_one :contact, :as => :contactable
7 end
8
9 class Label < ActiveRecord::Base
10 has_one :contact, :as => :contactable
11 end

Now to set up the fixtures.  All you need to do is specify the contactable name and contactable_type for each contact and we are done.

 1  # User
2 music_industry_person:
3 username: person1
4 password: secret
5
6 # Label
7 label1:
8 name = Some Indie Label
9
10 # Contact
11 fred:
12 contactable: music_industry_person
13 contactable_type: User
14 first_name: Fred
15
16 sam:
17 contactable: label1
18 contactable_type: Label
19 first_name: Sam

As you can see, a piece of cake!

Update:  Phil knew a one liner way to do this:

1  sam:
2 contactable: label1 (Label)
3 first_name: Sam

 

Writing a tinymce plugin for image uploads using Rails and attachment_fu

By Scott Roth on January 15th, 2008

Tagged with: rails, tinymce, attachment_fu, tutorial

Tinymce is a pretty nice browser based rich text editor (RTE).  We are using it successfully in one of our applications to provide a user friendly way for non-techies to have some control over the styling of content they create.  However, one glaring deficiency in the included set of plugins is that there is no way to upload an image (or any file) for use in the RTE.  This makes sense when thinking about it, as file upload requires a server side component - something that the client-side tinymce package needs to be agnostic about.  So, being a good lazy web citizen, I tried to get google to write the plugin I need for me.  Searching turns up several options - if you are on a PHP backend.  It seems no one has shared their approach to doing this with a Ruby on Rails backend yet.  So, I did it myself and am going to outline the process here for posterity.

Getting a basic plugin working (aka: the plumbing)

I started my quest on the tinymce wiki page dedicated to plugin development.  I downloaded the dev version of tinymce as instructed, which includes a sample plugin named '_template'.  FYI, we are using a 2.x version of tinymce.  According to the wiki, due to API architecture changes, the process will be a bit different if you are on a 3.x version.  Rename the _template plugin and copy it into the plugins directory of your tinymce installation.  You'll see 2 files right away: editor_plugin_src.js and editor_plugin.js.  Copy the _src file into the other one for development purposes; this is the file that is actually read.  At the end we will copy back into the _src file and compress the editor_plugin.js file, which is the one that is actually used at runtime.  Open the editor_plugin.js file and replace all the references to 'template' with your plugin's name.

Now you need to open wherever you have your tinymce.init() method and add your plugin in there.  Specifically, add your plugin name on the 'plugins' line to register it and on your theme's button line ('theme_advanced_buttons1' for me) so that the button will show up.  You also need an image for your users to click on.  Create one (or there is a template.gif in the sample plugin if you want to use that for now) and put it in the theme image directory (themes/advanced/images/[pluginname].gif for me).

Do a hard refresh on a tinymce instance and, viola, you should see a button for your totally useless plugin.  Some javascript alerts will probably pop up as the sample plugin is alert happy out of the box.
 
When you click that button, you are going to want a popup page where the user can specify the file to upload.  Let's set that up.  In editor_plugin.js there is a function called 'getControlHTML' - change 'mceTemplate' to whatever you want your function name to be - I chose 'doUpload'.  Match that name in the 'execCommand' function.  In execCommand make sure that the template['file'] line points to a real html file.  (There is a sample popup.htm in there.)  Ok, now refresh tinymce and click the button - you should get the sample popup.

The front-end

Ok, now all the infrastructure is in place.  We should be able to wire everything up now.  The plugin that I wrote is actually a bit more complex than the code I'll show here as I created some more advanced features like an option to select a file from the list of files that have previously been uploaded into our system.  Because of time and space I'll show some simpler code here though.

We need to take the sample popup.htm and change it to support a file upload.  Something like this:

 1  <html xmlns="http://www.w3.org/1999/xhtml">
2 <head>
3 <title>Image uploader</title>
4 <script language="javascript" type="text/javascript"
src="../../tiny_mce_popup.js"></script>
5 <script language="javascript" type="text/javascript"
src="../../utils/mctabs.js"></script>
6 <script language="javascript" type="text/javascript"
src="../../utils/form_utils.js"></script>
7 <script language="javascript" type="text/javascript"
src="../../utils/validate.js"></script>
8 </head>
9 <body>
10 <form action="/binaries/upload"
enctype="multipart/form-data" id="binary-edit-form"
method="post">
11 <p><label for="binary">Upload a file:</label><br/>
12 <input id="binary_uploaded_data"
name="binary[uploaded_data]" size="30"
type="file" /></p>
13
14 <p><label for="binary_title">Give it a
title</label><br/>
15 <input id="binary_title" name="binary[title]"
size="30" type="text" value="" /></p>
16
17 <p><label for="binary_contents">Add a
description</label><br/>
18 <textarea cols="40" id="binary_contents"
name="binary[contents]" rows="5"></textarea></p>
19
20 <input type="submit" value="Upload!" />
21 </form>
22 </body>
23 </html>

All we have really done here is create a front-end with a form that posts to your rails app (/binaries/upload) and with field ids that your attachment_fu enabled model class is going to recognize.  The javascripts included at the top are some tinymce magic.  They are not all needed for this simple example, but they probably would be as you flushed out the functionality you need.  For example, if you wanted tabs in your plugin interface or wanted to do some validation.

The back-end

For my example, we will assume that you have a Binary model that is already mixing in attachment_fu and a Binary controller.  If you haven't used attachment_fu before, Mike Clark posted a great tutorial on getting it set up.  Here is the upload method in the controller (this is who you are posting to):

1  def upload 
2 binary = Binary.create(params[:binary])
3 @insertString = "<img src=\"#{binary.public_filename}\" />"
4 render :layout => false
5 end

What a skinny method!  Thanks to the magic of attachment_fu, we can upload and save a binary file with just one line.  In the second line, we create the html string that will be inserted into the client page's DOM by tinymce.  We then render the view.  I am keeping this very simple for the example, but you can see some immediate enhancements to this controller.  For example, you may want some error checking to make sure that the binary uploaded and saved appropriately.  Also, if you are allowing uploads of any files, not just images, you'll need to be smarter about the html string you construct.  For example, if a PDF is uploaded, you may want to display your application's PDF icon as a link to the PDF, which would be code something like this:

1  @insertString = "<a href=\"#{binary.public_filename}\"><img 
src=\"/images/pdfIcon.gif\" /></a>
"

Now we need to return some javascript to the browser to insert our image into the RTE.  The view file (upload.rhtml using my code):

1  <script language="javascript" type="text/javascript" 
src="/javascripts/tiny_mce/tiny_mce_popup.js"></script>
2 <script language="javascript" type="text/javascript">
3 tinyMCEPopup.execCommand("mceInsertContent", false, '<%=
@insertString %>');
4 tinyMCEPopup.close();
5 </script>

This, also, is pretty simple.  Using the built-in tinymce function, mceInsertContent, we take our contructed html string and put it in the DOM and then close the popup window.

Check it out, y'all

Now we have all the pieces in place to try out our new plugin.  You should be able to upload an image and have it appear immediately in the tinymce textarea in your application.  If you are ready to go to production and want to follow tinymce best practices, don't forget to copy your editor_plugin.js to back to the _src file and to strip the runtime file down for faster loading. (Moxiecode suggests jstrim.)

As I mentioned earlier, there are many more interesting and complex tasks you can accomplish with a plugin like this.  The intent here was to get a full round-trip uploading plugin working that could be used as a foundation for future work.  Hopefully this helps you get jump-started.