Talking in Pictures

Category: Development

ScreenSteps Desktop 2.7 Now Available! Download ScreenSteps 2.7

Creating a New Person in BatchBook Using the Ruby Batchbook API Wrapper

We have recently been migrating from Highrise to Batchbook for our CRM software. Though Batchbook isn’t nearly as pretty as Highrise, it has some killer functionality in regard to integration with other services we use as well as a pretty slick way for adding custom data fields. It also has an API that makes it easy to integrate with our existing apps.

The API has a Ruby wrapper so it should be a snap to implement. Except that there was a documentation failure. It wasn’t that the documentation was bad. It just wasn’t there. So here are a couple of examples to help anyone who might be using the Ruby wrapper. Hopefully this will save you a few hours of scratching your head.

The Ruby wrapper uses ActiveResource, which is pretty slick. The good thing about this endeavor was that I learned a lot more about ActiveResource which I hadn’t really paid attention to until now.

Setup

To start using the library all you need to do is [download the batchbook.rb file](http://github.com/batchblue/batchbook) and stick it somewhere in your app. I add it to the `lib/` directory.


Fix Settings

The current version of the batchbook.rb file on github has localhost as the domain. You won’t have much luck accessing the API at the localhost:3000 domain. Hopefully they will update this soon, but if they haven’t just change the batchbook.rb file on lines 41-44 to look like this:

 self.host_format = '%s://%s/%s'
 self.domain_format = '%s.batchbook.com'
 self.path = 'service'
 self.protocol = 'https'

Start Using

To start messing around with this I just run script/console from the terminal to get into my Rails app. Then enter:

require 'batchbook'
BatchBook.account = 'your_account'
BatchBook.token = 'your_api_key'

Creating a New Person With an Email

Creating a person is easy enough.

person = BatchBook::Person.new person.first_name = ‘john’ person.last_name = ‘doe’

But what if you want to add an email address? This WON’T work:

person.email = 'john@mail.com'

That is because Batchbook has this concept of locations. So a person doesn’t have an email address. They have a location labeled “work” which has email, phone, city, etc.

So to add that email address, do this:

location = BatchBook::Location.new
location.label = 'work' ## You need this line or it won't save
location.email = 'john@mail.com'

Now, before you call location.save you need to do one very important thing. The location is a nested attribute of the person, so you need to add a path prefix option. Do this:

If you haven’t already saved your person, do so. This will assign an ID to the person object, which you are going to need.

person.save

ActiveResource then posts the information to http://youraccount.batchbook.com/services/people.xml

Now add the prefix option to the location.

location.prefix_options[:person_id] = person.id

This is part of ActiveResource and will add a prefix onto the url. If you don’t add the prefix, ActiveResource posts to /services/locations.xml. That isn’t what you want. The API needs to get a POST to /services/people/#{the_id_of_the_person}/locations.xml. By adding the prefix_option person_id we tell ActiveResource to add the people/#{the_id_of_the_person} to the front of the locations url.

Now just save.

location.save

That’s it. In hindsight it makes sense. But it sure had me confused last night.

Webinar: Why Your Documentation is Useless and How to Fix It
Download the free webinar to learn why your documentation/knowledge base is ineffective and what simple steps you can take to improve it.
Bookmark and Share

Revolution Data Grid Webinar Posted

Two weeks ago we hosted a webinar discussing the new Data Grid control available in Revolution 3.5. Revolution is the cross-platform development environment that we write all of our desktop software in and ScreenSteps uses the Data Grid control extensively. In the webinar we show how we integrated the Data Grid into ScreenSteps 2.5 and share some tips and tricks that will prove useful to anyone working with Data Grids.

The webinar is about 70 minutes long with a little over half of the time spent presenting and the reset spent answering questions from attendees. To watch the recording just visit the archive page.

Bookmark and Share

Data Grid Webinar

A few weeks ago Kevin Miller, Bill Marriott (both of Runtime Revolution) and I put on a webinar that introduced the new Data Grid in Revolution 3.5. The data grid was originally developed for ScreenSteps so that we could provide our customers with a much more responsive UI when working with large libraries and lessons. We were thrilled when Revolution decided to integrate it into their core product.

Given the extremely positive response by attendees, Greg and I thought people might be interested in seeing how ScreenSteps 2.5 uses data grids throughout the application. So we’ve added a new webinar to our webinars page entitled Using Data Grids in Revolution 3.5. In the webinar we will show you:

  • The various UI elements created using the data grid.
  • The techniques used to create some of the visuals.
  • The techniques used to hook the data grids up to data from SQLite, stacks, folder contents and the web.

We also plan on providing ample time to answer questions people might have. So join us on Thursday April 30th if you want to improve your data grid chops.

Sign up for webinar

Bookmark and Share

Recovering From a Disasterous Git-rebase mistake

Yesterday was adding the finishing touches to a marketing redesign of our screenstepslive.com site. This had been through many iterations but I felt that I finally had things the way I wanted them. ScreenSteps Live is entirely programmed in Ruby on Rails, both the web application and the marketing/sign-up area. We use Git for all of our version control.

Following standard Git practice, I was working on "marketing" branch that I had created from our "master" branch. Earlier in the day I had made a small update to the master branch to fix a small bug. In preparing to launch the updates to the marketing site I decided to do a git-rebase.

I’ll go into the details of how rebase works in a second, but basically the idea is to update the changes with a child branch (marketing) with changes that have been made to the parent branch (master). I ran into a few problems with the rebase and decided to abort, which has always worked before, but not this time. At least it didn’t work the way I expected it to. After aborting the rebase my marketing branch was at the same state it had been the day before. I had done a LOT of work in that 24 hour period. Basically all of my changes were gone.

Extreme panic set in. I had lost my css, my copy, my design, everything. I looked frantically for a way to recover from my disaster.

Option 1: Time Machine

Time Machine has saved me from myself more than once in my life so that was the first place I went to. Checking the backup I could see that I had a backup from about an hour ago. That was much better than losing an entire day’s work, but I had still done a lot of work in that last hour. What was more, I had finished the work. There is nothing worse than having to finish something twice. So I began to look for different options.

How Git Works

how-git-works.png

To understand the problem you need to understand how Git works internally. Whenever you make a commit with Git you are taking a snapshot of how your repository looks at that moment. The commit is assigned a sha1 hash (basically, a unique id), a message and a parent. The parent is the sha1 hash of the direct ancestor of the selected commit.

A git branch really doesn’t know anything more about its lineage than its direct parent. It also doesn’t know anything about its children. Branches are put together by stringing together a line of parent ids.

So What Happened?

Here is how things went. Oftentimes when doing a rebase you will run into conflicts that you have to resolve before the rebase will complete. It usually isn’t a big deal. But for some reason git had been acting funny because I had replaced a file titled "Movie.png" with a different image file called "Movie.png". I don’t know exactly what the problem was but it caused an issue with the rebase. Instead of resolving the conflict I decided to just to git-rebase -skip for that commit. Apparently this was a bad idea.

Right after that another conflict popped up. I decided that I really didn’t need to do a rebase and that this was going to be more of a pain than it was worth. I was just going to do a merge so I issued a git-rebase -abort command. The way this has always worked for me in the past is that all of the updating of the child branch with the parent branch is undone and you are right back where you started before you issued that "git-rebase master" command.

But not this time. Apparently issuing the git-rebase -skip command changed the point that my branch would rollback to, which was about 24 hours ago. Since git commits don’t know anything about their children there was no way for me to "fast forward" the branch to where I needed to be.

The Solution

Even though things looked bleak I was pretty sure of one thing – Git doesn’t usually delete commits from its database. That meant that my finished version was somewhere in there, I just had to find it.

I quickly searched the internet for ways to find commits that were no longer attached to a branch but didn’t find anything. So then I just started digging around in the .git directory of my project.

And I found a solution.

In .git/logs/refs is a list of text files. These text files have a history of your commits and merges on a branch.

media-1238070241727.png

I opened up the log for my marketing branch. Above is the relevant part of the log. I have highlighted the rebase that went bad.

media-1238070336956.png

But here is the interesting part. The log lists the commit’s sha1 (1) and the commit’s parent (2). You can see that in the image above.

So the solution was simple:

git checkout -b marketing_recovery 0b4354e5b95394c43

This created a new branch based off of my finished marketing update (note: You don’t have to enter the full sha1 hash of a branch when referencing it, just enough so that Git knows which one you are talking about).

There is one caveat: I lost the history of the branch but in this case it didn’t really matter. I was just happy to have retrieved my changes.

Lesson Learned

I still don’t know exactly what went wrong. It seems that git-rebase -abort should have taken me back to where I wanted to be. But I do know that I will not be using git rebase-skip again anytime soon.

Bookmark and Share

Cancel Forms And Avoid The If Then Statements

One of the big pains with Rails form helpers is that they don’t have a cancel button. No, problem – that is easy enough to add in. Just use a second submit tag like so:

            <%= f.submit "Create" %>
            <%= submit_tag "Cancel" %>

Now, if the user clicks the “Cancel” button a “commit” param with a value of “Cancel” will be submitted.

This is nothing earth-shattering. I have found this technique on various blogs. But then they all suggest checking for this parameter in the update or create method of your controller. I don’t like this because it makes you add in extra “if-then” statements. I really hate “if-then” statements. They make the code so much harder to read.

So what to do?

Use a before filter.

before_filter :check_for_cancel, :only => [:create, :update]

Then add in your method to check for the cancel parameter in the commit message.

  private

  def check_for_cancel
    if params[:commit] == "Cancel"
      redirect_to admin_spaces_path
    end
  end

That’s it. So now, if anyone clicks on the “Cancel” button on an edit or new form they will be redirected to the index.

If you really wanted to you could make the Cancel button submit the cancel parameter as part of the model hash. You would do it like this:

            <%= submit_tag "Cancel", :name => "model[cancel]" %>

You would just need to update your check_for_cancel method to check for that param. I prefer the previous method though since it is more generic.

Bookmark and Share

ScreenSteps Live: A Case Study on Ruby on Rails – Part 2 – Figuring Out the Code

In my last post about developing ScreenSteps Live with Ruby on Rails (which was far too long ago) I talked a lot about what led to me getting started with Rails development. In this post I want to talk about what were some of the things about Ruby and Rails that I found really useful and what things were really confusing.

Once again – a little of my background. When I started this I had a music degree from the Berklee College of Music, knew some basic HTML and was at least competent at using CSS thanks to the book “CSS: The Missing Manual“, which I can’t recommend enough.

So I was by no means a programming expert. Concepts such Classes, Modules, ActiveRecord, View Helpers, Partials, Arrays, and Hashes were all totally foreign to me. I had done some database work several years ago where I got to dig into SQL commands a bit. This background at least gave me a good understanding of how relational databases worked.

The Stuff That Confused Me

Here are some of the things that initially confused me about Ruby and Rails:

Block notation

It looks something like this:

@posts.each {|p| p.some_method}

For some reason that totally confused me. Once you figure it out it is wonderful and very powerful. But as I read books and searched the internet I could find all these things that mentioned blocks but didn’t define what they were or how they worked. I think that I will do a post soon about the important things I wish I had known about blocks but I don’t have space for that here. Now that I understand them I can find plenty of information on them. Isn’t that always the case?

Ternary operators

url.blank? ? "Preview not available" : url

That type of stuff totally threw me for a loop. All it is doing is evaluating an expression and returning a value depending on the value returned by the expression. It is short hand for an if-then statement. But those ? and : are very intimidating when your code vocabulary is limited.

Array Operators

posts.collect {|p| p.title } posts.select {|p| p.title == "My Post"}

I didn’t like that stuff at all, mainly because I wasn’t comfortable with arrays yet. That compounded with the block notation had me dong a lot of head scratching.

The Stuff I Liked

(more…)

Bookmark and Share

ScreenSteps Live: A Case Study on Ruby on Rails – Part 1

At Blue Mango Learning Systems we primarily develop two applications:

Distributing a product for Mac, PC and running a hosted web service is a lot of work, especially when there are only two people in your company. Therefore we have had to choose our development tools very carefully. For us, the most important aspect of any development tool is our ability to quickly iterate over a product until we feel that we have it “right”. Really, for us, all other considerations fall way behind. If we can’t iterate efficiently then we are going to move on to another tool.

Ruby on Rails has proven to be a great tool for this type of development. There are a lot of people getting into Ruby on Rails so I thought some of you might be interested in my experience. I think that ScreenSteps Live is an interesting case study in the benefits and drawbacks of Rails, so over the next couple of months I will be posting some of the things that I have learned as I have dived into the Rails world.

First, a little background on myself as a programmer and ScreenSteps Live as a web app.

ScreenSteps Live Struggles to Come To Life

I have no background as a programmer. Well, almost none. We first got the idea for ScreenSteps Live back in late 2006 or early 2007. At that time I had never even attempted to program a web application. I knew some basic html, enough to throw up a web page, and enough php to do some basic includes. But nothing beyond that. I also had programmed some smaller desktop apps with Revolution but only after extensive help from Trevor.

But we needed a web app. Trevor wasn’t going to have time to do it so we decided to outsource. I won’t go into all of the details on this but our first attempt didn’t work out so well. Suffice it to say that after 2 months we had nothing and were out a few thousand dollars. All I can say is be very meticulous in checking out the people you are hiring to develop your stuff. We weren’t and it came back to bite us in the form of lost time and lost money.

(more…)

Bookmark and Share

A Little Revolution Does A Developer Good

Round here we develop all of our desktop applications using Revolution. I recently attended the RunRevLive 08 conference in Las Vegas where one of the speakers was Robert Cailliau, the co-developer of the web. Robert spoke on “Programming systems and the birth of the Web”. Following a very interesting presentation on how the web came about he discussed some characteristics he thought a good programming language should have:

  • You should not need the reference manual lying open next to you.
  • A good assignment operator.
  • The less “swear” characters the better. These are characters from the top of the keyboard and are like the top shelf at a newsstand – dirty.
  • You should not need lots of comments.

His point was that you spend most of your time reading your code, not writing it. Therefore the language should be easy to read and understand. Since Revolution uses an english-like syntax it fulfills all of Robert’s criteria.

(more…)

Bookmark and Share

A Little Help Please

Over the last few weeks we have been shifting the primary focus of ScreenSteps Live to manuals. In doing so we have been looking at ways to easily integrate the manuals you create into a variety of different applications.

One feature we recently added was the ability to fetch a list of manual lessons that has been filtered by tags. For example, if I have a manual for my web application I can tag all of the lessons that discuss managing users with “user management”. I could then add some javascript (supplied by ScreenSteps Live) to my user management screens that displays all lessons from my manual tagged with “user management”. As I continue to add lessons and make updates based on user feedback those lessons pertaining to “user management” would automatically show up in my web application.

(more…)

Bookmark and Share

Screen Recordings

We have been getting a lot of questions lately about the videos on our site. I just use a few simple tools to create them:

Recording: iShowU

It is simple and fast. All it does is recording. No effects or editing but it works well for what it does.

Screen Highlights: Mousepose

This is a great little app for highlighting the screen. You should also check out OmniDazzle though I have never used it.

For editing I am just using QuickTime Pro. I highlight the areas I need to delete and delete them. Then I use the QuickTime Pro “Export for Web” feature. We used to host the videos on our site but when TUAW linked to us we got so many video views that it brought the site down. Now we host the videos on Amazon S3 and it seems to work pretty well.

There is a new app out that I am going to take a look at when I get a chance called ScreenFlow. It looks great but I haven’t had a chance to try it out yet.

BTW – We also get people asking if ScreenSteps records video. It most definitely does not. These little 4-7 min. videos take several hours to create. Screen recordings are a major pain. That is why we created ScreenSteps. We use video as a quick intro and then fill in all of the other documentation with ScreenSteps.

Bookmark and Share
Screensteps Support Suite

ScreenSteps is the most effective tool for creating and delivering customer tutorials and guides.
Learn about the ScreenSteps Support Suite