http://fablednet.posterous.com Most recent posts at posterous.com Thu, 06 Oct 2011 20:20:10 -0700 Thinking about iterators http://fablednet.posterous.com/thinking-about-iterators http://fablednet.posterous.com/thinking-about-iterators

Tonight I ended up putting together a visual aid for the each and select array iterators in Ruby. I was thinking, how do you show what is happening when you have called each, or select, on a collection? Suppose you are new to programming, or respond more to visual or visceral example than text-based ones? Brief code is elegant and can be beautiful on the page, but there are times when that's not enough, or doesn't match a particular learning style. 

I've had a project like this in my head for a while -- doing an in-depth visual guide for each of the Ruby enumerables and array methods -- as a way of "owning" my own knowledge on each method (as well as getting better at information-design).

Translating shows where you mis-understand the original language, and finding metaphors helps you make connections that are strong and rooted in your own way of understanding. This was a quick sketch and it's rough, but it was pretty fun to do so I wanted to put it out there. We'll see if more comes out of this.  (P.S. The day I can do a good one for inject will be a good day, indeed!). Feedback welcome!

selecting_squares.pdf Download this file

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Sat, 04 Jun 2011 21:37:00 -0700 Notes from Quantified Self 2011 http://fablednet.posterous.com/thoughts-on-qs http://fablednet.posterous.com/thoughts-on-qs

It's been a couple of weeks since I got back from the first annual Quantified Self conference, in Mountain View California.  This was a gathering of about 400 "quantters": people who self-track and self-experiment, whether by using hardware devices (like the zeo, or fitbit), software applications, or a computer and Excel. Corey and I attended since our web application, MercuryApp, is a life-tracking journal. We wanted to be a part of the weekend, present our work, and meet and learn more about the community. 

Of the 400 people who attended, approximately 100 presented work, led talks, or created a poster about their work. Because of the high ratio of participants, the community feels very alive -- people are actively making things, breaking things, making them again, and working with each other. The attendees were diverse: there were hardware programmers, health policy makers, visual artists, poets, software developers, PhDs and more, all drawn by some aspect of personal science, mood-, health- or life tracking. The diverse range of interests reminded me a bit of the interdisciplinary nature of ITP, where I went to graduate school, and the energy and interdisciplinary nature of the community bodes well for a new field that I imagine will be a household word in a few years. 

On the first day, I presented MercuryApp in a 5 minute Ignite talk, and then spent the two days going from talk to talk, listening to folks and writing down interesting ideas. There are too many and too diverse to roll into one blog post, but there are a few themes that jumped out at me. 

The conference opened with Gary Wolf presenting a talk called "What is the Quantified Self?".  It was a great opening for some of the big QS questions, especially with regard to the act of tracking itself, which is a central activity of the field. He presented a beautifully visualized data-graph of the last 10 years of his meditation habits, but he focused not on the times he meditated, but on the absences -- the days he skipped.  He used the skipped days as a way to address the concept of habit, and pointed out that despite the fact that he skips quite regularly, he considers his daily meditation a habit. This rang true for me: many things I do "habitually" are often skipped, and yet the skipping does not destroy the habit. This talk contextualized the idea of "relapse" or "falling off the wagon" as not necessarily an enemy of a habit, but as a collaborator in maintaining one.  

The idea of habituation came up frequently in many contexts, and is something that people (not just "quantters") struggle with. How do you, as an individual, adopt a new and healthy habit beyond the honeymoon phase? How does a software application developer make their application easy and frictionless enough to use that a user more than a few times? How do we all in an increasingly distractable world find stability in habits -- do we have to make them games? Is making life into games simplistic? There is going to be a lot of interesting work in the "habituation" (and conversely, "relapse") fields in the near future. 

Patti Brennan of Project Health Design presented another interesting concept she termed "ODL": Observations in Daily Living. This is a theoretical context where health practitioners work with patients to identify their own stories to use as metrics for discovering their emotional state. So, for example, rather than asking a patient to simply record when they are "angry" or "sad", help them identify repeatable times that they feel angry or sad (e.g. their own stories -- "It's Sunday night", "my partner has just left for the week"). Effectively, it's "story-driven tracking" using labels (such as events in their own lives) that the person understands, as opposed to doctor-driven tracking using labels (such as names of emotions), that the doctor understands but may not resonate with the patient. I am very interested to see developments in story-driven tracking, and how this can be helpful to people in maintaining health.  

Margaret Morris, a researcher at Intel, led a session on mood tracking where she wanted to expand the idea of mood tracking from placing oneself on a "happy -> sad" continuum to thinking more broadly about the role of anxiety and discomfort in achievement and daily living. In some of the anecdotal sharing in the room, it became clear that there is a similar journey that people experience when working towards something that is important for them (and that consequently makes them feel "happy" when they achieve it). The pattern involves a distinct stage of unhappiness -- "anxiety" and "panic" were named more than once -- but ends in a sense of increased happiness / well-being. Morris encouraged people building mood tracking applications to be aware of the texture and usefulness of emotions that we tend to label negatively (and thus see as "bad" place to spend our time). There is a certain resonance here between the traditionally "good" connotations of "habit" and the traditionally "bad" connotations of "relapse"  -- that Gary addressed in the first talk. 

The conference ended with a bit of perspective as Kevin Kelly talked about how Information is fastest growing entity on the planet -- with the exception only of meta-data (information about information) -- and that data is becoming a new media in itself. 

I am a bit mind-boggled, and this blog post talks about maybe 1/10 of the fascinating developments in this field, any of which could be expanded into a larger post, conversation, or lifes work.  I'm excited to be part of this community and fully expect to be blogging more frequently about certain aspects of QS as we continue to build our application.  I'll end by saying that I'm really excited to see such a convergence of technologists, psychologists, policy-makers and artists thinking and exploring health and well-being. And if you haven't heard of Quantified Self yet, I recommend bookmarking the blog and learning about something that is going to be much more pervasive and rich in the years to come. 

 

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Thu, 03 Feb 2011 08:13:00 -0800 Getting To Familiar http://fablednet.posterous.com/getting-to-familar http://fablednet.posterous.com/getting-to-familar

I spent last week at a  four-day-intensive studio on learning to program for the iphone. It was run by Pragmatic Programmers and I recommend it.  I chose to go because I want to learn iphone programming, but wanted guides for what I imagined would be a rocky takeoff, since I was struggling against my own instinctive, initial dislike of the language and platform. (It worked, btw. I'm excited now.)

During the week I learned a lot, and thought a lot about learning. How much initial learning is really just pattern recognition, making sense of a very blurry landscape.  I'm a kinesthetic / experiential learner, for better and for worse, and often my first responses -- be it to people, places, or codes -- are stronger viscerally than cognitively. After a time of looking at something (or being somewhere), things fall into place, but at the beginning it is very much an equal blur that needs to be processed experientially somehow.  

So while this "experiential brain" is poking around, how does the rest of the learning take place? How does it move through to the cognition phase? Being able to process what is meant by the symbols in front of me really doesn't happen until after a "getting familiar" phase, more akin to touching an elephant's leg than learning about his digestive system.  

Imaging that initial learning of a new language is like looking at code with syntax highlighting turned off --  not in your IDE, per se, but in your brain.  

The IDE might show the code in perfectly highlighted syntax:

Uncommented

but, maybe you "see" it as all red. There are no landmarks, it's hard to see what is important and what's peripheral, and there may be a "this is new!" sense of alarm accompanying it:

All_red

So just looking at code helps. Reading it with your eye like braille, letting the new bumps and cadences register without going into what they mean.  Getting to where looking at the new code or IDE does not give you that jarring intake of breath, that quick eye scanning to find your place. Being in that state puts you in a defensive posture which can serve as a barrier to information coming in -- you might be rushing, you might be panicing, you might be simply copy-pasting, or even giving up.

For experiential learners, before you begin "hello world", maybe sit back and explore yourself in the new environment ("Um, ..world..? Hello..?").  Get a feel for a piece of code or an IDE as a formal structure before attempting to grok it cognitively.  Are there many windows all over the screen? Is the code verbose or terse? What type of symbols do you see, and, is the effect to clutter the page? Clear the page? Highlight certain structures? What does it feel like? Do you know where you are? What metaphors does the environment use, and are they familiar to you? What are the menus? Do this until you feel kinda like you "get" where you are, even if you don't know what it's doing yet. 

Thinking about seeing code and context brought to mind the work of an artist and poet, Austin Kleon, who has published a book of poetry called Newspaper Blackouts, in which he starts with a full page of newsprint and a black marker, and blacks out all but words he shapes into a poem.  Not only do I like his work, but this way of seeing made me think about how you might "see" code after knowing a language or framework better. You might look at codes and immediately see the contextual groups:

"Ah, yes, view callbacks", you murmer to yourself, and begin implementing them: 

Blacked_in

After a while, the noise drops off and you "see" the callbacks more like this: clearly and simply, well-placed in space, tools for your use.

Whited_in

The calm of this last image is striking (as an aside, I can see why Matz invented Ruby! It really does improve programmer happiness). This calm, though, comes from getting to cognition. 

So learning is both. Orienting in your space, and using your tools.

It's interesting to think about what you're seeing and what someone else is seeing, when you're looking at the same piece of code. It's so different based on where you both are in the process of learning. Thinking about what people see might be helpful in teaching, as well. If you do learn this way, give yourself the space to get comfortable and don't jump to judgment on your style. 

All in all, it was a great week. And now that I've gotten this out of my system, stay tuned for my iphone app sometime in the not too terribly distant future!

 

 

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Wed, 12 Jan 2011 13:23:07 -0800 I'm Still Standing http://fablednet.posterous.com/revisiting-daily-standup http://fablednet.posterous.com/revisiting-daily-standup

Hey all, 

Last year I wrote a post about how much I liked standing up by myself.  I'm updating now b/c I lost the original image, and I've been asked about it since.

A couple years ago, I had a period of working from home, alone, and missed the camaraderie & mental organization of my daily group standup.  So I codified my practice and came up with a simple sheet that I would fill in every morning. It had: 

  • Date
  • Yesterday (what I did yesterday)
  • Today Planned (what I plan to do today)
  • Today Happened (what unexpected things crossed my path today... usually jot them down as they occur)

I'd then fill it in, stand up, and read it out loud. Oddly enough, it helped me focus, tremendously. 

I later added: 

  • Float (a place to note things that need to happen soon, but don't necessarily fit on the top-5 to-do list)

I then went back into the public workplace and brought this with me, filling it out before our daily standup and bringing it with me to each one.  Other people had their own methods, but for me, the act of sitting, then writing WITH A PEN, got a mind-body-organize-and-get-centered thing going on that got me off on the right foot every day. Then I could plunk it on my desk and use it as a to-do list.  Each standup sheet complete's its life-cycle when it's used as input for the next one. 

I've contemplated making a simple web app that handles all this, but it hasn't floated to the top of my priority list yet. Besides, for me at least, brain to hand to pen is really nice circuit.

My printer is on the fritz but I'm attaching a PDF of what I use if you'd like to download it and give it a try. Also, bonus! You can see what I'm doing today as I've attached my standup for the 12th!  

DailyStandup.pdf Download this file

My_standup_011211

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Fri, 31 Dec 2010 11:25:51 -0800 2010 Reflections http://fablednet.posterous.com/2010-reflections http://fablednet.posterous.com/2010-reflections

About six weeks ago, I quit my job. I had a nice, steady, Rails gig here in Chicago that had been a challenge for a while but had gone stagnant. When I was hired, it was clear that their application needed a total overhaul: it had minimal test coverage (less than 20%), the content was difficult to find, and there were a slew of other usability issues from a development and end-user standpoint. They also did not have in-house processes in place for development, having outsourced all development before this time.  

It was a whirlwind year in which we re-allocated in-house resources to redesign the application based on research and need; implemented a daily stand-up meeting; built a development team; rewrote critical parts of the site and streamlined others, and whipped the site into shape, increasing the performance by 100% and the test coverage to 90%. It was a fun time, we had built a strong team, and the company was better for it as they now   have the in-house tools to grow their site as needed.  But, after this was over there wasn't that much left to do; it was rapidly becoming more of a maintenance job.

During this same time, in the summer and the fall, Corey Haines and I started working together to build MercuryApp.com -- an application I'd built a version of for personal reasons a few years back, then let languish.  In a nutshell, MercuryApp helps people make decisions by tracking their feelings over time. We got caught up in developing and got excited about the project.  I was able to go part time at work during the summer and we ended up spending many full days coding and planning. We learned that we work well together and were both excited about the potentials of MercuryApp. We could see a lot of possible uses. Talking to other people we found they would often suggest new ways to use MercuryApp to track different aspects of their lives.

Add these two things, and a few dollars we each had stashed away in savings, and suddenly the idea of working full time on MercuryApp seemed like a possibility. We tried a few avenues for additional funding to avoid hitting our savings, but found we were at too early a stage to attract interest.  It didn't feel like it mattered, though: filling out the applications and practicing "pitching" was helpful. We learned, fine-tuned our ideas about MercuryApp, and thickened our skins. It was fun! And it was fun because we knew that whatever happened, we would take the time to work on the project.

So as I sit here writing, I am entering 2011 from my beautiful home in Rogers Park where we have set up MercuryApp Central: a wonderfully warm and bright office where we work side by side, testing, coding, building, talking.  I feel a huge sense of excitement to be in a space focused on making things and writing code.  No matter what happens with the MercuryApp, I will be the better for it, as every day I am getting up and coding, and creating something I am passionate about. 

The other day we went to the Chicago Bootstrappers Breakfast and met a lot of folks in Chicago who are also on this path. It is invigorating to be around people who are taking small or large leaps to work on their ideas. There are so many developers who have ideas and the skills to implement them.  There was a lot of energy in the room as people shared their own experiences and ideas. I felt proud to be in their company.

For a long time I've been wanting to take a "sabbatical" -- a self-funded year to work on my own projects. This is not the shape of the sabbatical I envisioned -- for one, there's a lot less money saved up, and less time paid for -- but it's the sabbatical that's feasible right now. I'm looking forward to coding, building MercuryApp, growing stronger as a developer, and finding time to explore other aspects of life as well by taking walks, exploring Chicago, relaxing, and doing other types of side-learning (hint: I got an arduino for Christmas!).

I'm using this blog entry to mark where I am in time, and also to encourage people who feel stuck and/or passionate about something to find a way to start working on it. I think doing this will make life more fulfilling and more of an adventure.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Thu, 04 Nov 2010 19:39:00 -0700 Birthday Cake http://fablednet.posterous.com/birthday-cake http://fablednet.posterous.com/birthday-cake

Last year, I made my friend Andrew a cake for his birthday. This year, we're going behind the scenes to see how the cake was built.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Thu, 01 Jul 2010 03:05:00 -0700 Integrate Google Event Tracking with JavaScript http://fablednet.posterous.com/blog/2010/06/30/integrate-google-event-tracking-with-javascript http://fablednet.posterous.com/blog/2010/06/30/integrate-google-event-tracking-with-javascript

This post discusses easy ways to integrate Google Analytics Event Tracking in your website. Event Tracking is a tool that broadens your ability to track user interaction with your website. Prior to event tracking, using Google Analytics gave you rich information about your page views. With Event Tracking you now have a wealth of information about usage on your non-page reloading events such as AJAX calls, hover events, mouseovers -- anything you would like to define and track. (Just make sure you have an account first).

It's dead simple and, after setup, takes a one-line call to a JavaScript method supplied by Google:

pageTracker._trackEvent(category, action, opt_label, opt_value);

You just have to get the right arguments to that method, so you know what you're tracking. In the Google tutorial the example is predicated around sending the arguments to the _trackEvent method inline on an onclick event. Instead of doing that, which will create redundant script tags in our views, let's label our markup in such a way that we can grab a collection of trackable elements via JavaScript and submit them automatically, on a click (or other) event. There are a few ways to do that, the most straightforward being class names if you are not using HTML 5, and data attributes if you are. The key is to make sure you have a consistent naming convention that you can then parse for details.

Imagine we have a "News Tray" on our website. It has five stories and you can read a story by clicking on a number (1..5) or clicking on the headline. It also has a fancy scroll bar for when an article overflows the reading area.

To see how users interact with our News Tray, let's set up a category called...NewsTray. Then let's name the different actions we want to track. How about... downArrow, clickNumber, and clickHeadline. And finally, with clickNumber and clickHeadline, we might want to send more information (the number and the headline, respectively) than just that they were clicked. Those can be our optional labels.

With that in mind, to label the markup using class names we might do this: Give each tracked element an eventTracker class, followed by a string of encoded classes:

class= "eventTracker track_NewsTray_downArrow"class= "eventTracker track_NewsTray_clickNumber label_2" class= "eventTracker track_NewsTray_clickHeadline label_9800-news-update"

This would allow us to fetch them all like so (using jQuery), and bind them to a function we write called trackEvents, that sends the data to Google.

$(".eventTracker").bind("click", trackEvents);

If we used data attributes (recommended for its simplicity and clarity), we might do this:

data-event="tracker" data-category="NewsTray" data-action="downArrow"data-event="tracker" data-category="NewsTray" data-action="clickNumber" data-label="2"data-event="tracker" data-category="NewsTray" data-action="clickHeadline" data-label="9800-news-update"

And then fetch them all using jQuery as well. Note that in this example I bound all my elements to a "click" event, but bind to whatever event you want to track, and be as creative in your use of labels and selector fetching as you like. The last step is to write the function to bind to the collection of elements. For class names, I used a couple regular expressions to parse out the data and send it to Google if we are in a production environment.

var trackEvents = function(e){   var classNames     = $(this).attr('class');   var actionMatches = classNames.match(/track_(\w+)_(\w+)/);   var labelMatches   = classNames.match(/label_([\w\s&\-\d\.]+)/);         var eventCategory   = actionMatches[1];   var eventAction       = actionMatches[2];   var eventLabel        = labelMatches ? labelMatches[1] : "";       if(location.href.match(/your-production-url/)){       pageTracker._trackEvent(eventCategory, eventAction, eventLabel);    }}

For data-attributes I'll leave the exercise to the reader. That's it! All you have to do is label your markup and you are automatically sending data to Google. Once that's done...you can then log in and see information about who's clicking what widget on your site, and how much. I'm showing a screen shot of the stats on our news tray, so you can envision what the results will be like:

Media_httpimgskitchco_iotyb

 

Exciting, right? And that's only the tip of the iceberg. You can drill down for more information, and analyze it in a myriad of ways. In closing, not only is it useful, it's fabulously addictive! It helps you see what people use and what they don't, so that you can fine-tune your site accordingly. Happy Tracking.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Mon, 31 May 2010 04:57:00 -0700 How to set up Cucumber and RSpec for a non-Rails project http://fablednet.posterous.com/blog/2010/05/30/how-to-set-up-cucumber-and-rspec-for-a-non-rails-project http://fablednet.posterous.com/blog/2010/05/30/how-to-set-up-cucumber-and-rspec-for-a-non-rails-project

Often times when we use Cucumber and RSpec (and by 'we' I refer to Rails developers, sorry for the narrow focus here), we use them from within a Rails environment.

Here are some instructions on how to set up Cucumber and RSpec for a multi-file Ruby project in a non-Rails environment. Note: if you're here because you want to make your own gem, stop reading and check out jeweler instead. Jeweler will take care of it all for you with one command:

jeweler name_of_gem --cucumber --rspec

If you are not making a gem and just want to bootstrap your own project, here are instructions -- with explanations of what is what. Some may be obvious, but I find that when we are used to using generators it can be easy to overlook what they generate and why. It's the old "the gui made me dumb" syndrome. Therefore, I choose to both err on the side of verbosity in this post and include a link to a bash script that does it for you, at the bottom. For this example, imagine you are going to write a game of Tic Tac Toe in Ruby.

  1. Make sure you have Cucumber, RSpec and their necessary friends installed on your computer:
    sudo gem install gherkin  sudo gem install cucumber  sudo gem install rspec  sudo gem install webrat
    Note: sudo may not be necessary for your set up -- that's a matter of personal preference and your existing setup.
  2. Create project directory. For this example, say you're making a Tic Tac Toe project:
    mkdir tick_tac_toe
  3. Add the following directories and files for Cucumber and RSpec:
    # Cucumber  mkdir tick_tac_toe/features  mkdir tick_tac_toe/features/step_definitions  mkdir tick_tac_toe/features/support  touch tick_tac_toe/features/support/env.rb  # RSpec  mkdir tick_tac_toe/spec  touch tick_tac_toe/spec_helper.rb
  4. Add a lib directory where your own code will go. This is where all of your classes and files will live.
    # Your project code  mkdir tick_tac_toe/lib  touch tick_tac_toe/lib/tick_tac_toe.rb
    Note: some people prefer to have a named directory inside of lib and put all the app files in there. That would look like this:
    mkdir tick_tac_toe/lib  mkdir tick_tac_toe/lib/tick_tac_toe  touch tick_tac_toe/lib/tick_tac_toe.rb
    File organization is a matter of personal preference and I'd say if you're planning on having more than one file, use a nested directory, otherwise just place it directly at the root of lib.
  5. Set up the files so they will recognize each other.
    1. open tick_tac_toe/features/support/env.rb and add the following lines: $: Explanation: the first line adds the lib directory to your load path. The load path is stored in the $: variable. Yes, that is "$:", without the quotes. If you type $: in irb, you'll see an array come back with all of the directories that are looked in by default when you require files. The second line requires spec/expectations, which is what you use in RSpec all the time. Now you can use this behavior in Cucumber. And the third line requires your very own tick_tac_toe.rb file.
    2. Open up spec/spec_helper.rb and add the following lines: $: Explanation: It's that load path again ($:). And you're doing the same thing as before, adding your lib directory to it. Notice the difference between the Cucumber setup and the RSpec setup with regard to this line? spec_helper.rb is only one level below lib ("/../lib") while env.rb is two. It's all just about finding the files where they are in the tree. The second line requires spec, (RSpec). And the third line requires your very own tick_tac_toe.rb file.
  6. That's it! It boils down to this file structure:
    tic_tac_toe--features----step_definitions----support------env.rb--lib----tic_tac_toe.rb--spec----spec_helper.rb----tic_tac_toe_spec.rb
    And then add your *.feature files inside of features/; your step files inside of features/step_definitions; and your *_spec.rb files inside of spec/.
    P.S. I wrote a bash script to automate this for myself and put it on github: feel free to use or improve.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Sun, 25 Apr 2010 21:08:00 -0700 Upgrading to Snow Leopard from Leopard http://fablednet.posterous.com/blog/2010/04/25/upgrading-to-snow-leopard-from-leopard http://fablednet.posterous.com/blog/2010/04/25/upgrading-to-snow-leopard-from-leopard

The process was pretty straightforward, though I went through it twice. I thought a quick write up might be helpful for someone else since there were a couple points that gave me pause.

I bought the Snow Leopard CD from Apple for $29. I decided to reformat my drive entirely rather than simply upgrade -- my mac is coming on three years old, why keep around all that cruft that's gathered over the years.

A few posts I read said you needed restart the computer while holding down "c" with the CD installed in order to reformat: I did not need to do this the first time (when I was still on Leopard). I did need to do this the second time, when I had already upgraded to Snow Leopard and wanted to repeat the process. I was able to insert the CD, double click the "Install" option, and then choose "Disk Utility" from the utilities menu at the top of the screen. I spent a few minutes looking for "Utilities" on the install dialog box and didn't see it. It was perhaps too well designed: subtle enough to be easily missed.

I selected my hard drive and chose "erase", then selected "Zero Pass" erase from the "security options" dialog. I did not feel the need for a 7-pass government-certified erasure: it's only my cruft I'm getting rid of, not national secrets. This took a few hours, so I did it before bed.

Once that was done, I quit disk utility and clicked the "install now" icon on the Snow Leopard modal dialog box. Install took a while (hour or so) and then started up smoothly.

I immediately ran "Software Updates", which brought me up to 10.6.3, and allowed my magic mouse to work.

Regarding Time Machine. I was a little uncertain at this step and tried once to migrate my user account from my old machine using Migration Assistant. I had to rename the account since my new account had the same name. I was able to select which files to bring over, though for some, like Applications, it was all or nothing.

When this was complete I was disappointed: each of the copied over directories had a little red circle and x through it: the message I got was that I did not have permission to access these files. Was it because my previous account was an admin and I was an admin as well? Would I have to log out and log back in as the old user (now renamed to sarahleopard)? I didn't like it. Plus, it had brought over all my apps (at my own request) and I didn't want a bunch of them. I also read that if you do this, you risk over-riding newer versions of the apps with your backups. So I decided to wipe and reformat again -- and get it right this time.

The second time, after following the exact same steps up until the Time Machine part, I simply accessed my Time Machine not through Migration Assistant but just manually by clicking through to the directories I wanted from the most recent backup: Backups.backupdb -> Sarah Gray... MacBook Pro ... 2010-04025-151235... Macintosh HD... Users... sarah... Documents... And then dragged over the Documents I wanted to my hard drive. I did the same for Applications, only bringing over my copy of Office.

My final question was, would using the same external backup drive for TimeMachine on Snow Leopard that I had used on Leopard overwrite my previous Leopard backups? I had seen a couple of scary threads from users who believed they had lost all their data doing this. So just to be safe, I called Apple Support and confirmed directly that you can use the same hard drive and not lose your previous backups (i.e., not have the hard drive reformat to the new OS).

I tried it, backed-up my new, spartan and clean Snow Leopard setup and can still easily access my previous Leopard states.

All good. I hope this helps someone embarking on the same task.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Fri, 05 Mar 2010 03:33:36 -0800 That mental space behind the couch http://fablednet.posterous.com/blog/2010/03/04/that-mental-space-behind-the-couch http://fablednet.posterous.com/blog/2010/03/04/that-mental-space-behind-the-couch Is where new features go when you forget to scope and prioritize them, relying instead on the deluded fantasy that the new feature you are talking about is just "this small thing" that we'll do "now". It is easy to fall into this delusion because the meeting discussing the new feature was very genial. You can tell a feature has been stashed in that forsaken crawl space when:
  1. It has no story cards or to-dos attached to it -- it's just something you're "taking care of".
  2. Alternately, it has one card -- with few or no details. The title of this one card could translate without too much trouble into "Write Big New Feature". If you were questioned about that card you would grudgingly admit that it could be an umbrella for ten or twenty other cards, including things like: figure out what this feature actually does, CRUD all the resources (once it becomes clear what the resources are), and design UI.
  3. Other cards or to-dos are left open and unfinished while you "take care of this quick thing". Leaving them open supports the delusion that you're only gone for a second -- to the corner store, as it were, and not fleeing to Argentina to start a new life.
Other things you might also find in that crawl space when you start poking around it are:
  1. The fictional project deadline someone in your company insisted on having set in stone (that is conspicuously about half the time it will take to complete the project).
  2. The unfinished tails of "completed" features, e.g., "Yeah, the widget is done! I mean, it doesn't work in Safari yet and the we're gonna change the background image from a gremlin to a frog, but essentially, it's done."
  3. The chocolate bar that had no calories because you ate it standing up.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Tue, 15 Dec 2009 00:40:00 -0800 How awesome is that? (A public service announcement for using gems, plugins, and otherwise tested code) http://fablednet.posterous.com/blog/2009/12/14/how-awesome-is-that-a-public-service-announcement-for-using-gems-plugins-and-otherwise-tested-code http://fablednet.posterous.com/blog/2009/12/14/how-awesome-is-that-a-public-service-announcement-for-using-gems-plugins-and-otherwise-tested-code

Ok, so let's say you have some code from some guys you worked with once, some really really smart guys, and the code is... well, no, the code is awesome. It extends Rails in such a way that you can do all sorts of hitherto unheard-of magical transformations that make your life so much easier, and your code so much easier to read. And to write. And to understand.

OK, now, when you say it extends Rails, you don't actually mean like a patch or anything. And, actually, you don't even mean like a plugin or a gem. But it extends Rails in a really really awesome way.

OK, so what if the code is untested, really...dense, difficult to read, impossible to understand (even if you really really wish you understood it), and reliant on many other files? And so what if the other files the code depends on aren't in a plugin or a gem. Well, technically, some of them are. But some of them aren't! Which is fun! Because then it's not all conventional-like. Just super magical. I mean, who cares?

Because this is awesome. It gets even awesomer, because as you're busy using these magical transformations -- you don't even have to learn how to do things the regular way. You can just awesome it up and go home.

Which is fucking great. Until you decide to upgrade your application into the future, where everyone else has been living for a while. You know, Rails 10.11 -- or something really awesome like that.

And then, wait a minute, all the code breaks.

The app doesn't start. The code is no longer compatible. And worse, it's no longer compatible in a really really obscure way. That you really wish you understood. But you don't.

How awesome is that?

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Mon, 30 Nov 2009 20:28:00 -0800 Setting up multiple branches from a github repository http://fablednet.posterous.com/blog/2009/11/30/setting-up-multiple-branches-from-a-github-repository http://fablednet.posterous.com/blog/2009/11/30/setting-up-multiple-branches-from-a-github-repository

This is a quick writeup about getting started with git branching via github.com. It covers creating a github repository then branching and pushing changes to it from multiple machines (work computer and a laptop).

While I have had a github account for a while, I hadn't explored branching until recently when I wanted the ability to branch our Rails app. Because the company where I work is redesigning and adding features to our application, we need the ability to maintain a master branch for the next few months that can be deployed to production on a moments notice but at the same time be able to do new development safely in a separate location (with its own deploy environment). This was enough to merit switching the app from subversion to git and figuring out how to do the basic branching that I would need to do. While in real life I transferred a Rails app from svn to git, the steps below use a dummy directory. I recommend always starting with a meaningless example until you get the hang of things -- I didn't want to learn how to do it on my app. As a note, to transfer a Rails app from svn I simply cloned my Rails app, recursively removed all the .svn directories:

rm -rf `find . -type d -name .svn`

and initialized it as a git repository. (I did look at git-svn but I couldn't see the benefits other than bringing over the version history which we have elsewhere, so I simply started clean).

  1. Create a new repository in github.
  2. Follow the steps listed on the page. My demo example is straight from github as follows:
    mkdir demonstration cd demonstration git init touch README git add README git commit -m 'first commit' git remote add origin git@github.com:sarah/demonstration.git git push origin master
  3. Go to second machine and check out the repository. A slight complication arose because I happen to have two accounts on github: my personal account and the one I access for work. Since I need to access those both from the same laptop, I had to follow these instructions to set up two separate ssh keys. Definitely worth being aware of -- I had some head-scratching before I realized that you can't store the same SSH key across accounts. Anyway, because of that, when I check out the repo on the laptop, I reference
    git@gin3
    instead of
    git@github.com
    where gin3 refers to the entry configured in my
    ~/.ssh/config
    file, where I configure the host like so:
    Host gin3  Hostname github.com  User git  IdentityFile /Users/sarah/.ssh/id_rsa_github_gin3
    So, I check out the code on the second machine.
    git clone git@gin3:sarah/demonstration.git
  4. On the first machine I create a branch and add a file to it, in order to see the differences between new_branch and master:
    git branch new-branchgit checkout new-branchvi new-branch-file.txt git add .git commit -m "adding a file to the new branch"
    And then, to put the new branch on github, simply:
    git push origin new-branch
  5. Next, delete the branch locally, which sets up for the next step where you can track the branch remotely. Note that you can't delete the currently active branch, so I had to checkout the master branch in order to run the command below:
    git branch -D new-branch
  6. Create a new branch from the remote branch:
    git branch -f new-branch origin/new-branch
    Then you will see, by typing git branch that you have two branches.
  7. Make a change
    git commit -am "adding a line of text to the readme in new branch"
  8. Push the branch back to github:
    git push origin new-branch
  9. Go to the other machine and checkout the branch
    git fetchgit checkout --track -b new-branch origin/new-branch
  10. Then, I can add a file or make a change and push back to the branch.
    vi file-from-laptop.txt git add .git commit -m "adding a file to new-branch from my laptop" git push origin new-branch
  11. Back to machine #2, make sure you are on the new-branch branch, and then pull:
    git pull

And you will see all the changes and can continue to work in this fashion as long as you like.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Sun, 23 Aug 2009 06:22:00 -0700 Early Cucumber impressions http://fablednet.posterous.com/blog/2009/08/23/early-cucumber-impressions http://fablednet.posterous.com/blog/2009/08/23/early-cucumber-impressions

I've used Cucumber a few times before. For one, I coded the Mastermind puzzle in the RSpec book, adding a few extra features for my own game-playing edification. This was done initially in the service of an assignment and became a learning exercise.

Secondly, in my first venture into pair programming, we used Cucumber to drive out some features of a Rails project I am working on. I had already set up a few scenarios, but they were basically languishing until this pairing session. It was a pretty smooth session: not only were the features easy (essentially basic CRUD and view logic), but my partner was an expert at Cucumber, quickly pointing out a bunch of time-saving features like tags and inline tables to pass data. Learning from doing, with someone else, is so much more thorough than learning from a book. Also, since I'm a one-key aliasing fetishist, we set up aliases to run the features: u for all the features; and f for those tagged @focus. I love that. The session made Cucumber feel intuitive and easy to use.

But, still. It's a new framework and new to me and I'm still in the slog-through phase -- "getting" some of it and furrowing my brow at other parts. As well as having a bunch of opinions and an earful of opinions from other users on both sides of the fence. So I've decided to use it this week to drive out a rewrite of the authentication process on an existing site. I am also using it for as-yet unwritten features on a new app. So as I start the process, I thought I'd write down some of my existing impressions, and then track how they change (if they do) during the next week or so. Too easy to write? I like RSpec. While I've heard some complain about it trying to be too much like natural language to be intuitive to developers, that doesn't ring true for all for me. The should syntax is structured enough for me to feel safe working within it (and by "safe", I mean, I am secure in the knowledge of how the syntax works: I feel I can lean back on it w/o thinking. And, added plus, it reads like a sentence fragment to me). Cucumber, otoh, gives me that "you're dangling in space" feeling. Is this fragment of natural-sounding language going to successfully run a test? Or is it too natural-language-y to work in a way that gives me confidence. For instance,

When I follow "Logout" Will call a predefined webrat step for me, I don't have to do a thing but have that link on the page and this step will run:

When /^I follow "([^\"]*)"$/ do |link|  click_link(link)end

But what about if I switch up my sentence, because it sounds so much like english in my head that I'm not thinking in constraints, I'm thinking in words. Like so:

When I follow the logout link

or

When I log out

or

When I logout

etc.

Each of those will spit out some code for me when I write them, on the first pass through: a new step that I can then define, as so, respectively:

When /^I follow the logout link$/ do  pendingendWhen /^I log out$/ do  pendingendWhen /^I logout$/ do  pendingend

There's a hesitation there, as well as a freedom. Freedom: you can write whatever you want, get a step, and implement it. Hesitation: Is my sentence structured to take advantage of a pre-existing step? What happens if I change the wording of my step at some point b/c I hadn't quite captured what I want to test as clearly as I could have and Cucumber caters to my linguistic comfort? Oops -- I'll have to change the regex that defines the step. In short, these lines of text seem brittle, because you can change them so easily, in a way that RSpec statements do not. For instance, RSpec, to my mind, has more obvious constraints:

@cat.should be_purring

Can not be written as:

@cat.should purr

without breaking the syntax.

Because the rules are more obvious, they're easier to adapt up front rather than butt up against later. Of course, you can write custom matchers with RSpec, and my examples are trivial, but the RSpec path to learning feels more explicit to me. Cucumber, like Rails, strikes me as a deceptively simple framework: it's "ah!" at first glance, and then "oh...?" a bit later.

Really use for client communication?

One of the canonical Cucumber examples given is that you will be able to work out business requirements in the same document and language that you use to run your tests. There is no longer a need for a separation of documentation, and this should allow you to work more fluidly with the client.

Having previously attempted (in a past life) to write a small, php-based, "workflow-helper" tool, in which I sat with the client, talked out the workflow of a site, and used those sentences to create html links to pages in order to "map out" the process in a browser... I was skeptical. Now, disclaimer: the thing I wrote wasn't sophisticated (and neither was my client). It was, at best, grappling at an idea of demonstrating workflow in a way that could feel "real", and coming up with a sub-par implementation of an idea that is actually implementable in Cucumber - as, using Cucumber you can actually change and test what's on the pages, not just that they're there.

But, my goal of translating words into prototypes in order to gain buy-in from the client on the spec showed me that no matter how much perceived communication there may be, at the end of the day you can still be on different pages about how a product will work. This left me wondering how much of this "specs as communication document" is realistic.

That said, just yesterday I sat with my current client and wrote out a bunch of scenarios and features in Cucumber. We concluded the meeting with a great sense of shared clarity. He later asked me if I could email him those files, as, for him, they had taken on the authority and buy-in of business documents. Wow! Maybe I'm wrong about this being a non-workable fantasy. It was an interesting moment, to say the least. My initial enthusiasm dampened, though, as I understand that best practices dictate not writing more than one scenario at a time. In that case, should I be sitting with the client all day, pinging back and forth with him? That doesn't seem realistic with our real-world time and business constraints.

I met someone recently who says he uses Cucumber to drive out working prototypes to show a client. He makes the entire suite pass in the browser before he starts to work on passing the tests. In short, he uses Cucumber as prototype-creating engine to show a client working HTML mocks before coding in the functionality (i.e., before going back and making each each test fail in the red-green-refactor cycle we're used to). Good idea!

So over the next weeks, I'll be continuing to learn and use Cucumber in a couple of different applications, testing my assumptions and becoming more familiar with the framework. I'm sure I'll do things that are foolish (and hopefully one or two that are smart), and in the process see if I become comfortable with Cucumber and find it something I'd like to use more substantially moving forward or not. I'd love to hear any input on uses, it's perceived strengths and weaknesses, and any tips for skill-building.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Tue, 18 Aug 2009 02:36:00 -0700 Pair Programming Firsts http://fablednet.posterous.com/blog/2009/08/17/pair-programming-firsts http://fablednet.posterous.com/blog/2009/08/17/pair-programming-firsts

I had a great time pair programming last weekend. It was the first time I had done this in a formal, our-computers-are-connected-and-we're-typing-at-the-same-time kind of way. I've programmed with people at the same computer, collaborated with people on different computers in a casual throw-ideas-back-and-forth kind of way, and done the passing-the-laptop-around thing, as well. But, a lot of my development time has been alone. For instance, I had a job for six years where I not only worked alone, but I telecommuted. During this time I lived in Brooklyn, Austin, Denver and Chicago (though not all at the same time). This was great and terrible at once: I had wonderful freedoms and benefits (cross-country travel and NY salary with TX income tax rates, to name a few), but I missed having other developers to learn from and play with.

I've heard great things about pair programming, but the idea of it frankly made me nervous. The lack of privacy, someone looking over your shoulder, all your typing mistakes, all the failures to remember how to do this, that or the other: laid out on the table in real time. I felt a little bit like I'd rather find anything else to do than actually go through with it, and, given that we started so late in the day, I think I was headed in that direction. There are only so many times you can wash your hair!

But for all that, there was still a voice inside me whispering that, hey, this might be fun. This might be really, really cool (and, not to mention, good for you!). And guess what? It was awesome. It helped that I was working with someone who is an expert in pair programming -- an excellent programmer, experienced pair and all around kind human being. This gave me a comfort level, made what could have been technical difficulties flow smoothly, and created a good environment. It was also fun because I got more experience with Cucumber and started to get a better feel for it, both the things in it that I like, and those that I don't. More on that later.

I finished knowing that this is something that I want to do more often. The flow of ideas between two people, the easy bouncing between code and tests, the way the specifications developed in a way that made sense and felt straight-to-the-point, the funny we-typed-at-the-same-time kind of moments -- all of this made coding feel like a playful game. I also felt very attuned to the shaping of the application: alert and present. Now, we were working on a pretty easy project, so it might be a different animal when the technical challenges are more vigorous, but I'm looking forward to that as well: my guess is that by breaking those challenges down into small steps and talking them through, that they become more clear and manageable.

In all, it was the most energizing three hours of programming I've had in a while. I felt an excitement and movement that has stayed with me since. And when we were done I felt kind of clean: the layer of anxiety was gone, and we just were who we were. I think that kind of honesty is good -- for people and for code. I would suggest to anyone who hasn't tried it to give it a shot. Start with something easy or that you're comfortable with if you're nervous, and let someone more experienced be the guide.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Wed, 08 Jul 2009 06:24:00 -0700 Integrating the MIT / SIMILE timeline with Rails http://fablednet.posterous.com/blog/2009/07/08/integrating-the-mit-simile-timeline-with-rails http://fablednet.posterous.com/blog/2009/07/08/integrating-the-mit-simile-timeline-with-rails

This is a brief entry on how to populate the MIT / SIMILE timeline with dynamic data culled from a Rails application via a controller action that returns JSON. There is a plenty of existing solid information on the timeline itself, as well as a tutorial on integrating it with Rails and one focused on a simple html implementation. All these sources are clearly written and give basic usage tips. I recommend them and will not duplicate them here.

However, none of the sources demonstrated how to get dynamic data into the timeline via URL (they focused instead on creating the JSON / XML inline in the view via iterating through collections, or having it pre-existing as an external text file), I'm adding that information here in the hopes that someone else building in Rails finds it helpful.

This code snippet focuses only on the loading information, the rest is snipped but can be found in the other listed sources (above). You simply pass an url to the loadJSON method, and make sure the url returns JSON. Note that however you want to build the route -- it's own action or a json representation of the index action for events -- will work. Here I created a timeline action.

Timeline.loadJSON("projects/13/events/timeline.json", function(data, url) {     eventSource.loadJSON(data, url); });}

In your controller simply return the JSON. Again, non-relevant code is omitted:

def timeline  events = []  @events.each do |event|     # dates need to be utc      events  event.start.utc.to_s, :end => event.end.utc.to_s,                        :title => event.title, :description => event.description}    end    respond_to do |format|      format.json{        # the timeline needs the key events to point to the array of event objects:        data = {"events" => events}        render :json => data.to_json           }               endend

And that's it!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Tue, 07 Jul 2009 02:58:00 -0700 Solo standups (that you can do sitting down) http://fablednet.posterous.com/blog/2009/07/06/solo-standups-that-you-can-do-sitting-down http://fablednet.posterous.com/blog/2009/07/06/solo-standups-that-you-can-do-sitting-down

I love daily standups, but what happens when you're standing (working) alone? Or it's not in the organizational culture? Even if you're lucky enough to have a standup meeting at work, you still have to find the thread of continuity from your work yesterday to your plans today and be able to communicate it in just a minute or so.

Personally, I find it hard to get a focused start on a workday if I don't know where I am on my road map of things to do and have a list of tangible discrete tasks. It's easier to feel overwhelmed or just kind of vague about what needs to be done. Also, when diversions occur, as they always do -- an unexpected bug or meeting -- it's easy to lose track of where the time went. People can get overwhelmed, let things pile up, veer down a different path without fully acknowledging the trade offs, or buy Getting Things Done and leave it unread on the shelf for a year. :) Enter the quickie, low-tech, solo-standup worksheet. This is a bastardization of various techniques I've observed in others, and I've found it to be simple, repeatable, and helpful enough to actually stick. I've used it for standup prep, centering myself when working freelance from home, and when working as the sole developer in an organization that doesn't have a standup culture. Instructions: take a sheet of paper and divide it into 4 sections: the first three roughly even, the last being the smallest. Xerox it a bunch of times, punch holes in them, and put them in a binder. Then each day, take 5-10 minutes at the beginning of each day to fill it out. These are the categories:

  1. Yesterday -- quick bullets of what you actually did yesterday
  2. Today Planned -- quick bullets of what you plan to do today. Filling this in helps you plan the whole day, and quickly structure the big items. It also encourages you to write down things you need to do, even if you may not want to do them. Once they're written down, they become much harder to ignore.
  3. Today Happened -- a place to jot down things that may have come up unexpectedly -- e.g., "impromptu UI meeting to discuss new sale". So when tomorrow comes and you didn't finish everything from yesterday, you can see what took its place.
  4. Floating -- This is for things that come up during the day that you'd like to get done, but don't quite fit in the plan. They're ideas you don't want to lose, things you might want to integrate into a later "Today Planned" category; or things that after a week or so you realize aren't that important anyway. Scratch them at the bottom of the page as the day goes, and keep a visual inventory over the weeks.

Here's an example of mine from July 2nd. Nothing fancy, but that's the point. Each day, you do a sheet like this -- and, over time, you have a binder of documentation you can flip back through.

I still use digital tools -- Basecamp and Pivotal Tracker come to mind, but this serves a slightly different purpose -- it's an act of personal attention / intention. Reading my sheet from yesterday and then putting pen to paper as the first act in the day is a simple habit that has a mind-calming effect. It's a way of acknowledging the process and keeping accountable to the steps along the way.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Fri, 03 Jul 2009 07:11:55 -0700 Hold the Candle, Read the Code http://fablednet.posterous.com/blog/2009/07/03/hold-the-candle-read-the-code http://fablednet.posterous.com/blog/2009/07/03/hold-the-candle-read-the-code Maybe you inherit an application, as I have. With an old test suite: some tests, but not too many. Written in Test::Unit, not overly clear from the wording what they are doing. Reliant of fixtures with evocative yet ambiguous names: @full, and @empty. But they're there. You run them. They pass.
def test_homepage_section
    assert !@empty.on_homepage?
    assert @full.on_homepage?
  end
Then one day, you're exploring some of the code covered by these tests in order to add a new feature to this particular corner of the site. Some code needs to be written, some needs to be refactored, all of it needs to be understood. It's the perfect time to port the tests to RSpec, as you've been doing little by little as time permits. Fixtures are replaced by Factories, underscored test names replaced by strings; and yet, as you get started, it's clear that whatever a particular test is asserting is simply not clear from reading it. Yes, '@full is on homepage', you say to yourself. But what exactly does that mean? Tests as documentation is a wonderful goal but this is more like tests as clues. Sort of faded-out, smudgy clues, gesturing in a particular direction -- "something important, over there by the staircase! or maybe by the flower-garden, I can't recall", the test murmers. Imperfect, cryptic, dimly-lit flashlights. Yet still, they help you read. There weren't many of them, and important areas were left untested, but the tests that were there you had to think were there for a reason: something important here. What is it. And so like knocking on ghost walls or tapping on teeth, use the tests as a guide to illuminate a workflow and logic from the application. You can find the walls where people thought the treasures were hidden or feared the roof might cave in. And then once there, you can tap on those walls, lift them up, look behind them, listen, repair, and see what's going on. Even in the weakest light, this reading was more focused than simply reading the code from top to bottom w/o tests. Because you weight everything equally then, read with a kind of equality of input that can mask what's going on, the quickness or intricacies of the plot, the way the methods depend on each other or don't. You might read faster, thinking you understand. There was something very old-school about it. We might want, both to inherit and to create, a readable, plain-text narrative of cause and effect -- whether a test suite, a mission statement, or a to-do list. And this is admirable, a good goal, I want it myself. But how often does that happen? More often than not we're left with smudgy remnants of intent, in language that has shifted and meaning that has slipped. The clear end may be no longer clear nor the end, and you're left with a chipped piece of an old idea trying to tunnel forward into clarity. Sometimes you have to throw it all away and start again. But sometimes, a little light is better than none. And the half-light of shadows is often all we have to see by. Hold the candle, read the code, assert.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Mon, 08 Jun 2009 04:34:12 -0700 Multiple File Upload using SWFUpload on Rails. Part II http://fablednet.posterous.com/blog/2009/06/07/multiple-file-upload-using-swfupload-on-rails-part-ii http://fablednet.posterous.com/blog/2009/06/07/multiple-file-upload-using-swfupload-on-rails-part-ii This part of the tutorial covers getting the files that you select via your swfupload setup to upload into your Rails application. Part I covers the setup: getting the external libraries, markup, and JavaScript all in place. You can find that here. This tutorial assumes you are using attachment_fu. The Flash / Rails principles would be the same if you are using Paperclip, but the syntax for the upload itself would vary. However, since the main sticking point is the fact that Flash doesn't send the session_id to Rails when it posts data, thereby denying Rails access to current_user or a valid session, it is my hope that this article will be helpful regardless of which attachment plugin you are using. The solution I used, suggested in part by Geoff Buesing, was to handle the controller actions used for the swfupload differently than the other actions. In short:
  1. Turn off the session for the actions in question
  2. Supply an alternative login method to get and authenticate current_user
So, to turn off and on the relevant filters in your controller:
before_filter :login_required, :except => [:create, :swfupload]
before_filter :login_from_upload_token, :only => [:create, :swfupload]
session :off, :only => [:create, :swfupload]
Now we are ready. Because we can pass additional parameters to the controller from the JavaScript used in swfupload, I passed the user activation code and used that to authenticate the user before allowing them to upload files. Note: in my app, the JavaScript is embedded inside of a Haml template: depending on what syntax you are using, your variable assignment may look different. The key is to create and assign a JavaScript variable using Ruby, and then pass it as a part of the post_params object literal that is sent within the settings object literal, like so:
==var activation_code = '#{current_user.activation_code}';
var settings = {
  ... flash settings
  post_params:{
    activation_code: activation_code 
  }
}
Then, you can go ahead and upload some images. The params look like this (yours will vary based on file name, other params, etc. But notice that the param Filedata is a reference to the image data): Processing Projects::Elements::AssetsController#swfupload (for 127.0.0.1 at 2009-06-07 22:29:53) [POST] Parameters: {"Filename"=>"zak-on-bed.jpg", "element_id"=>"33", "project_id"=>"16", "action"=>"swfupload", "activation_code"=>"ebbd3863ba95e8ff66ad5e0c69e4fa0e6653e36f", "domain"=>"sarah", "Upload"=>"Submit Query", "controller"=>"projects/elements/assets", "Filedata"=>#} When the params arrive, they are fed through the login_from_upload_token filter. To authenticate the user we look them up by their activation code and set the result to current_user:
class Elements::AssetsController  'Invalid User', :status => :forbidden if @current_user.nil?
 end
end
Once this is in place, all you have to do is handle the image data coming in from Flash. It is very simple. Assuming that you have set up your model with the ability to handle uploads using attachment_fu, you are simply setting the :uploaded_data to the :Filedata param, and filling in anything else you may be validating, such as title or created_by: def swfupload @asset = @element.assets.build(:uploaded_data => params[:Filedata], :title => params[:Filename],:created_by_id => @current_user.id) render :nothing => true and return if @asset.save end Here's a quick peek at my asset model, which is a polymorphic resource using attachment_fu:
class Asset  true
 has_attachment  :storage=>:s3,
                  :path_prefix=>"assets/",
                  :thumbnails => { :thumb => '120x69>', etc...}  
  
  validates_as_attachment
end
And that's it! Of course, you can customize the swfupload page using the built-in handlers to show status messages, pending uploads, image thumbnails as they appear, etc. But, it was my experience that the most vexing part of this process was the Flash / Rails interaction, and so I'll leave the UI customization to you. As a final thought, Rails is convention over configuration and for the most part this is great. But one of the side effects I’ve noticed in using Rails is that it is easy to sometimes turn your brain off and accept certain configurations as unassailable -- "the way things are". In this mindset, it can make finding a solution to a new problem more difficult. So be wary of that when you're stuck. It's possible that you need to talk to someone else to help you see the problem in a new light, or think about what Rails is doing and why; and what might be alternate ways of solving that problem. Good luck!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Fri, 29 May 2009 23:21:00 -0700 Design By Caste http://fablednet.posterous.com/blog/2009/05/29/design-by-caste http://fablednet.posterous.com/blog/2009/05/29/design-by-caste

Recently, en route to NYC, I was navigating through Chicago’s Midway airport. When I came to the Security Check there was a discouragingly large crowd of people pushing towards the gates. As we moved forward a few steps we came to three signs -- each marking the entrance to a separate line.

Each sign had a label and a graphic. Each traveler had a choice.

The first sign, I forget the label: but the graphic was of multiple people, including children, with multiple bags, crowded rather lumpishly into the frame. The label said something along the lines of Unfamiliar Travelers, High Maintenance Travelers, or People You Never Want To Be Stuck Behind In Line. I was definitely not joining this group.

The second sign had a line drawing of a fit young man in his thirties or forties. He sported a shoulder bag and a trendy hair flip. His sign? Casual Travelers. I hesitated in front of it and noted a feeling of fleeting disturbance that this representation of casualty and ease was male.

And then… sign three. Expert Travelers. It featured a woman in a pencil skirt, obviously traveling like an expert. My disgruntlement vanished. The line it flanked seemed short and swift.

I paused. The night before traveling, I’d watched a video by Corey Haines. Corey is a software developer who has embarked on a year-long project in which he travels around (casually? expertly? crying like a child?) wherever agile programmers beckon, pair-programming in exchange for room, board, and adventure. If you ever want to watch someone sit in on a rock a rainy forest next to a plastic gnome and discuss framework development (yes, I thought so) — look no further.

In this compelling piece of woodland discourse, Corey warns against those who preemptively self-categorize as experts. Granted, the critique was targeted at those with little or no framework development experience insinuating otherwise, but, it gave me pause: Was I really an expert traveler?

Do I slip my shoes off before reaching the metal table? Check. Have my laptop case unzipped as I approach the bins? Check. Pre-vision the hand gestures it will take me to remove my coat, stack my bags, check for metals — and keep my boarding pass in my teeth? Check! Expert Traveler indeed!

The funny thing is, once I peeled off to the right amongst the ranks of the other expert travelers, I realized that our line snaked further right than was apparent at its entrance. While High Maintenance and Casual travelers appeared to be moving steadily forward from Point A to Point B, we "Experts" were steered, like Temple Grandin's cattle, through a long and circuitous passage, out of view of a security checkpoint.

We walked, grimly demonstrating our expertise, strong silent types, all: laptops already removed from bags; grown men walking sock-footed through fluorescent tunnels; jackets flung over crooked arms; and boarding passes, held conspicuously in outstretched hands.

After a (long, circuitous) while, we hit the table, passed through expertly (though the man in front of me failed to anticipate the re-appearance of his shoes in a timely manner, causing a bottleneck), and went our separate ways, fanning out to cities and countries across the world. Leaving me to contemplate a number of things.

And, finally, my preference for the snaky line formation.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray
Thu, 07 May 2009 01:41:00 -0700 Chasing People through The Google http://fablednet.posterous.com/blog/2009/05/06/chasing-people-through-the-google http://fablednet.posterous.com/blog/2009/05/06/chasing-people-through-the-google

I love my dad. He's an original. And sometimes stubbornly so. For instance, when his originality is dried up and he's in a creative slump, he starts slinging language around like confetti, minting word-concoctions like wildwildwild, spoink, and metaNow.

What do they mean? Despite the fact that more often than not the new words are presented in some awesomely frightening font, such as showcard gothic, and are at least 70px high, no one actually knows. And more than one person has been burned by a quick defensive reaction when inquiring whether wildwildwild is actually a viable business plan. (Answer: of course!).

He loves PowerPoints and Word Documents, often writes without capital letters, and has a sixth sense for pronouncing words and names exactly... wrong. Syllables go where no syllables have gone before. And yet, somehow, he has some wonderful communication skills. He's smart, empathetic, a great listener, and is full of creativity. He has brought the world more than any one person's share of innovative programs and ideas. He has a theology degree from Princeton, was a community organizer in Chicago in the 60s (way before Barack), started schools in Harlem, and founded or supported the founding of multiple social programs in NYC, including being one of the founders of the Posse Foundation. Plus, he renovated a Brooklyn townhouse so me and my brother got to grow up imagining all the strange rooms we could live in. And then knocking down walls and making them.

Why all this? We were talking on the phone this morning. As usual, I was getting some advice from him about (of all things) communication. When we were wrapping up I asked what he was going to do today.

"I'm chasing people through the Google", he said, without affect. Meaning, I believe, that he's following up contacts and leads using our ubiquitous search engine.

I think that's the most awesome, and sort of poetically apt, way of talking about our online habits that I've heard in years. Certainly more descriptive than "Google Stalking". Reminiscent of lush jungles, except in this case we have one continuous ever-present underworld and overlord: The Google.

The Google contains everything: text, images, the earth, your house, the deep web, and of course time, both past and present. And you just kinda...climb in the search box (our generations answer to the Narnia wardrobe?) and go.

No irony whatsoever.

Chasing people through the Google.

I hope he catches them.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1289907/sarah_gray.jpeg http://posterous.com/users/5Avy6bP9ZOdH Sarah Gray fablednet Sarah Gray