RSS feeds are cool (in case you didn’t know)
When we started working on Spotstory, Aron and I had many conversations like this:
Matthew: “Oh, we should have a feature like [some feature]!”
Aron: “Yeah, and you should be able to get it via an RSS feed!”
Matthew: “Uh, okay … oh, and we could do this thing where we [do some other thing]”
Aron: “Definitely! Oh, and you should be able to get at it with an RSS feed!”
And so on.
Now, I’ve simplified this conversation a lot to make a point (that is, I’m not implying that Aron’s only contribution to the site’s design was to follow up each statement I made with “and we should make it available with a feed!”)
What I am trying to point out, is that from day zero we made a decision to have Spotstory be as open as possible, and a major aspect of that was to have data bubbling out of all these RSS feeds.
I didn’t quite appreciate this at the time (but I should have, since I’ve long been a “open an API to your software and people will do unexpected things that amaze you” kind of guy.)
Anyway, a couple days ago I was thinking, “It would be cool if we could have a list of recently created Spots in the sidebar of the blog.”
And then it occurred to me: there has to be a WordPress plugin out there somewhere that will do this. And if there is, I know we have the feed.
If you haven’t already, cast your eyes over to the sidebar and see a happy little list of the most recently created Spots on Spotstory. It took five minutes–literally–to put it together. (It took longer to write this blog entry!)
Special thanks to Chris Hatcher and his nifty SideRSS WordPress plugin and thanks to Aron, too, for having the foresight to make sure we did the right thing from the start.
Update
I just realized that if you’re reading this in a feed reader, you won’t see the sidebar! Oh, the irony.
No commentsOpenCoffee Boston
OpenCoffee is touted as “a place for people who love startups to hang out and meet.” That pretty well describes OpenCoffee Boston which takes place every Thursday morning from 10:00 AM to noon at Andala Coffee House. Andala is located in Central Square at 286 Franklin Street, Cambridge, MA.
This event has been going on for a little over a month, and I’ve spent at least a little time at most of them. The environment is quite friendly, the coffee is quite good, and I always come away having learned a thing or two.
Attendance is generally strong, and has grown slightly since it’s started. The crowd is mostly made up of web-oriented entrepreneurs, but there are folks with all sorts of backgrounds. I’ve spotted at least one venture person in attendance.
The coffee is good, the environment is very informal (no name tags!), and it’s easy to pop in and out just to catch up and say hello. Some people even work away on their laptops through the entire event.
So, if you’re remotely near Central Square and thinking about grabbing a coffee, come on by, meet a couple people, see a demo, hear about a new idea, or just enjoy a cup of coffee!
No commentsMoleskine Goldmine
I was in Harvard Square today, and being a few minutes early for my lunch meeting, I decided to pop into Bob Slate.
I haven’t been in there for quite some time, but I can always count on them to have a wide array of cool notebooks to drool over.
I was not disappointed: witness, in the accompanying photo, what can only be described as a Moleskine bonanza! Ruled, plain, squared. So many sizes, aspects, and page counts.
Just thought I’d share.
1 comment
Upgrading to Rails 1.2
If you have been following this weblog for a while, you have probably figured out that Spotstory is a Ruby on Rails application.
Over the past few days, I have been working to upgrade Spotstory from Rails 1.1.6 to Rails 1.2.3.
There is very little comprehensive information about some of the problems encountered when upgrading a Rails application from the 1.1.6 release to 1.2 (specifically, Rails 1.2.3).
Once You Freeze, Step Cautiously
Upgrading your Rails application is easy! Update, deploy, then go enjoy your apple pie! Right? Wrong.
% rake rake rails:freeze:edge TAG=rel_1-2-3
So far, so good. Let’s see if anything runs.
rake rails:update --trace rake aborted! uninitialized constant ActionController /usr/local/gems/rake-0.7.1/lib/rake.rb:1948:in `const_missing' config/../config/environment.rb:32
Why did this happen? Did the Rails installation get corrupted during the upgrade? No. Far, far simpler. On line 31 of config/environment.rb, I had a raw reference to ActionController. Due to major dependency changes in Rails 1.2, this no longer works.
# Rails 1.1.6 technique for setting session expiry: ActionController::Base.session_options[:session_expires] = Time.mktime(2037)
In Rails 1.2, it appears that this sort of configuration can not appear within the Initializer block. After moving session configuration out of the Initializer block, things started running.
Deprecations & Warnings
I decided that every deprecation message would be squashed and every warning removed. I worked on most of the warnings before even trying to get all our tests to pass; they were just too noisy for my aesthetics.
DEPRECATION WARNING: The :dependent => true option is deprecated and will be removed from Rails 2.0. Please use :dependent => :destroy instead. See http://www.rubyonrails.org/deprecation for details. See http://www.rubyonrails.org/deprecation for details. (called from has_many at vendor/rails/activerecord/lib/active_record/associations.rb:558)
(Yes, that link is actually printed twice!)
These deprecation messages are great — they tell me what has changed and how to improve my code, but they reference source files and line numbers within the Rails core. This is not helpful. I was able to find some instances of deprecated usage by recursively grepping our source (from within Emacs, which makes results electric). Very quickly, I turned to a heavier hammer.
ActiveSupport::Deprecation.debug = true
Toggling this debug variable exposes the full callstack which caused the deprecation message.
Here are the changes I needed to make in order to eliminate all our deprecation messages:
- Some model helpers have gone away or have changed in call syntax. Rewrite model methods in the following way:
Rails 1.1.6 Rails 1.2.3 Model.find_first Model.find(:first) Model.find_all Model.find(:all) Model.type Model.class.to_s Model.count(conditions) Model.count(:all, :conditions => conditions) - Has many associations no longer provide the has_ASSOCIATIONs? and ASSOCIATION_count methods. Rewrite:
Rails 1.1.6 Rails 1.2.3 Model.has_ASSOCIATIONs? ! Model.ASSOCIATIONs.empty? Model.ASSOCIATION_count Model.ASSOCIATIONs.size - Rewrite controller/view instance variable references:
@params, @session, @request, @response all become params, session, request, response. - Move to the new form generators.
form_tag ... end_form_tag
becomes:
form_tag do ... end
The same is true for form_remote_tag references. In addition, the form methods no longer need output-generating RHTML rules (remove the “=”).
- The link_to helper prefers a different way for specifying that a link will generate a POST operation.
link_to ... :post => true
becomes
link_to ... :method => :post
- Association dependencies now support more granularity, which means that the old-style:
has_many ... :dependent => true
becomes:
has_many ... :dependent => :destroy
- Add parentheses and remove whitespace between parens and method names to prevent ambiguity. Not clear why these issues didn’t cause issues in Rails 1.1.6.
Fixing Broken Tests
With our application beaten into quiet submission, it was time to turn to our tests. A good majority of our tests still worked, but a few changes were needed to get everything passing.
- Content-Type headers now include charset information; make test helpers resilient to the presence of charset.
- assert_tag with a string value for the :content option now performs a strict match against the content for any sub-tag. As a result, some :content options were converted to regular expressions.
Determining when a regular expression is necessary is not obvious, especially when the match text is embedded within another markup tag.
At this point, all of our tests passed.
Dependencies
Unfortunately, we weren’t done. The development server would unexpectedly give errors like:
User expected, got User
In addition, our User model would get missing_method errors for methods which clearly exist. The problem is an interaction between the Rails 1.2 dependency rewrite and plugins which have dependencies upon application models. Ramble On discusses a similar dependency issue.
We use a number of plugins in our application. One of these is a customized version of acts_as_commentable. This plugin defines the Comment model and expects a User model to be defined by your application.
In development mode, plugin models are not reloaded. The dependency infrastructure unloads the User model, but doesn’t realize that there are still live references from the plugin-defined Comment model. Subsequent references to a comment’s user information will generate an AssociationTypeMismatch exception giving the cryptic “expected User, got User” message. Because this is a reload problem, errors don’t happen on initial load. The errors start the second time a comment-displaying page is loaded.
Web searching didn’t reveal much at first. Some people recommended explicitly requiring the User model in application code. Others recommended replacing references to a User object with references to its id. Another solution called for explicit :class_name in the association declarations. Some of it worked some of the time; none of it worked consistently.
I started looking through the Rails dependency code and found that Nicholas Seckar (ulysses on IRC and in SVN) was responsible for much of the rewrite. After explaining my missing_method errors in an email, he replied:
See http://api.rubyonrails.org/files/vendor/rails/railties/CHANGELOG.html
Look under the changes for 1.2.0, 4th one down.
This references a late change to Rails 1.2 by Rick Olson:
Ensure plugins are in the Dependencies.load_once_paths collection by default. [Rick] If you really want your plugins to reload, add this to the very top of init.rb:
Dependencies.load_once_paths.delete(lib_path)
Ok. I need to reload my plugins. Bleh. Further, this has to happen in environment.rb, not in environments/development.rb. Bleh.
# Array of plugins with Application model dependencies.
reloadable_plugins = ["acts_as_commentable"]
# Force these plugins to reload, avoiding stale object references.
reloadable_plugins.each do |plugin_name|
reloadable_path = RAILS_ROOT + "/vendor/plugins/#{plugin_name}/lib"
Dependencies.load_once_paths.delete(reloadable_path)
end
None of this forced plugin reloading feels right. Rails should just figure it out, yes? More mail to Nicholas, leading to his response:
The problem is related to associations — the class object is cached and thus the class is never garbage collected, even though it is ‘removed.’ This causes all sorts of problems…
Since it only happens in development mode, it really doesn’t matter.
He’s partially right. It doesn’t affect production applications, but it really does affect peace-of-mind. I’m sure lots of people are freaked out when they bring up their upgraded app in development mode and find all sorts of things unexpectedly broken.
Update: I was wrong about the session configuration changes in Rails 1.2. I have updated this post accordingly.
28 comments
Locations, Locations, Locations
During the early days of Spotstory (you know, a couple months ago) we started throwing a lot of features at folks. Usually, we gave these new capabilities a brief mention in the release notes, and then hoped people would find them and use them.
A few nights ago, we were talking to a longtime user (in relative terms!) of the site. I mentioned Locations, and this person didn’t seem to know what I was talking about. So much for hope!
So, I figured that it was probably a good time to step back and cover some of Spotstory’s features in a little more detail. Since Locations were the inspiration, I’ll start this series of posts with them.
What is a Location?
So what’s a Location? It’s what it sounds like: a place somewhere on the planet! It’s a latitude and a longitude. They also have a name (e.g. “Parent’s House”, “Home”, “Ski Lodge”, etc.) That’s it!
Why do I care?
You can think of a Location as a bookmark for the face of the planet. It’s a way for you to watch a specific place for the appearance of new Spots. You can even get an RSS feed for the Location which is updated when new Spots appear.
How do I Create one?
Locations are easy to create. Just go to your home page and click on the edit icon next to ”My Locations,” you’ll find it on the upper right hand side of the page. From there, just follow the instructions.
You can create as many Locations as you’d like. Currently, the Locations you create are private.
If you’ve got any other questions, comments, or suggestions about Locations, or anything else, we always love to hear from you!
I hope you’ve enjoyed this intro to Locations! I’ve covered most of the details here but there are a few more neat things about them you’ll discover, I’m sure. So get started: go create a Location today for your home, your childhood home, your favorite vacation spot or any other place you fancy!
No commentsSeeding your user generated content site (or not)
We often get asked why we didn’t seed Spotstory with content from some other source. Certainly, databases with location data are easily obtained and integrated.
I imagine that anyone launching a site that depends on user generated content, or some other sort of social media, is going to ask themselves this question. I’m not sure that there is one right answer for everyone’s circumstance, but I can explain how we made our choice.
Pros
Here are a couple of reasons we came up for why we might use seed data.
- Empty sites are no fun We’ve probably all had the experience where we see a site’s launch announcement on TechCrunch or Mashable!, only to find the the site contains only three or four data records (usually someplace in downtown San Francisco.) Seeding with a pre-existing database seems to solve this problem.
This is the big argument for seeding, and, no doubt, for certain services it makes complete sense.
- Scaling You want to make sure your system scales to handle the large datasets (you hope!) you will have some day.
This argument is probably less often voiced, but it should be! It’s definitely the right thing for everyone to do: you can use seed data during your development process, and then discard it before you deploy. You can still keep it around in your development environment. This is what we do.
Cons
Here are some of the reasons against using seed data.
- The site is still empty anyway We’ve all seen this too: you go to a site, click on a link, or search on a latitude/longitude, or place name and get 1000 results. You click through them and find … nothing.
Aron and I discussed this at great length when we were getting started. We’d experienced many sites that were filled with this “empty” data and the sites just felt … empty. Big certainly, but empty nonetheless.
(I have a lot more to say here, but it’s a tangent to the topic at hand. I’ll write more about it later, I promise.)
- It’s illegal It’s mechanically easy to access and import data, but do you have the right?
Now, there is a lot of data in Wikipedia that would be appropriate and welcome in Spotstory. The problem is Wikipedia uses the the GNU Free Documentation License and Spotstory uses the Creative Commons Attribution-ShareAlike 2.5 License for all text content. Though these licenses share the same spirit, they are not the same.
Some might see this as a technicality, but we don’t. (And, yes, it is a challenge keeping unadulterated Wikipedia content out of Spotstory!)
In the end
In the end, we decided we’d start from scratch, and try to grow as much content as we could before we launched. We felt it was important that actual people discover and share the Spots. We thought it best that every Spot have associated with it a person who considered it interesting enough to share with the rest of the community.
Ultimately, this approach seemed most appropriate to the spirit of the site.
We’re based in the Boston area, and we’re happy at this moment to try and build a critical mass of interesting content for this area, and so far it seems to be working out well for us.
But, please, don’t let that keep you from creating Spots in other places! :)
No comments
Blame it on the rain?
Man, this is some crazy weather we have had over the past few weeks. For those of you not in the Boston area, Thursday was a fun day with rain, sleet, and a little hail. This weekend, a Nor’easter decided to visit, bringing large amounts of rain and violent winds.
This morning, we woke to find that the huge tree at the end of the street had been uprooted!
This house is just three doors down. Luckily, it appears that no one is hurt and most of the house is structurally intact; the root structure must be supporting most of this massive weight.
I don’t know when this tree was planted. Like most of Arlington, many homes in our neighborhood were built in the late 1920s. Since this is New England, streets are all tree-lined (if not, I’m certain some archaic statute would be violated). Most of the trees don’t appear to predate the neighborhood construction. This whole area was stripped of lumber (feeding the building demand in Boston) and used as farmland.
This raises some questions about our recently departed tree. It appears to predate the housing in the area. Why did it survive the 1920s construction? If this neighborhood was indeed farmland, was this tree present? Maybe it provided shade for a local farmhouse. We are on top of one of the Arlington hills and have good views of the surrounding land. On a clear day, you can even see into Boston.
About an hour ago, two trucks from a commercial tree service drove up to the tree, stopped for a minute, then drove off. Scared, maybe? Trucks from the Department of Public Works have just started showing up. Backhoes, front loaders, chippers .. no need to watch Extreme Machines today!
Update: And now a crane! The Arlington DPW is pulling out all the stops!
No commentsRelease Notes: April 14, 2007
We pushed an update of the system tonight around 11:15 PM ET. This release primarily fixes issues reported during our launch.
- You can now choose the representative image for Spots and Visits Until now, the image shown on the Spot page, or as a thumbnail next to a Spot summary, would simply be the first image that had been uploaded to the Spot. This was also true for Visits. With this release, you can choose which image should be shown. Just go to the Spot or Visit edit page, and the rest should be obvious. This was the by far the most often requested enhancement!
- New feedback interface The old feedback interface did a bad thing: after you would go through all of the trouble to send us feedback, we would send you to a page that was not where you were, and with really with no place to go! That was bad (and we’re sorry!). The new feedback interface uses a popup which let’s you resume your train of thought once you’ve been kind enough to send us your insights.
- Streamlined goecoding interface for Spots We’ve changed the way you tell us where a Spot is located. We’ve taken the separate address lookup, and latitude/longitude entry boxes, and combined them into a single one. We hope you find this arrangement easier to use.
- Spots can display an address Displaying just the latitude and longitude of Spots was initially neato, but it turns out the novelty wears off after while, and people just want to see the name of a town, a state, or a country. So now you can associate the actual name of a place, and not just the GPS coordinates, with a Spot. So, if it makes sense for your Spots to have an address, you can now update them with one.
- Many many other fixes and refinements Many fixes and refinements, both large and small and too numerous to mention, have been made!
Once again, we’d like to thank everyone who has sent feedback or dropped us an email for their time and effort. Many thanks also to everyone that has contributed a Spot, and especially those who have contributed more than one!
Future Updates
We’re going to keep updating Spotstory on a continual basis, but in the future look for each release to have a theme.
This doesn’t mean we won’t be reacting quickly to major problems like we always have: each release will still contain numerous fixes for critical bugs, or problems that just seem particularly pesky.
We haven’t finalized the date of the next release, but it will probably occur in early May.
Thanks again for being a part of Spotstory!
No commentsRecap: Berkman Thursday Meeting
As Matthew mentioned, I was at the Berkman Thursday Meeting on April 12th. I had a great time talking about Spotstory to everyone in attendance.
Thanks to Mike Walsh for the invitation and Erica George for help with some of the logistics.
Extra thanks to everyone who braved the weather on Thursday. From my office window, I watched as the weather cycled through sleet, rain, and maybe a little hail. The Red Sox may have been rained out, but the Berkman Blog Group persevered!
1 commentRecap: Boston Ruby Group
We had a lot of fun presenting at the Boston Ruby Group last night. We’d like to thank Tom Dyer and everyone else involved with organizing, setting up, providing space, and providing pizza.
Once again, the meeting was well attended: folks were standing along the walls and sitting on the floor. This month’s program was more Rails-oriented than last month’s, but few people seemed to mind that.
Eric Mill from thoughtbot gave a talk on REST and ActiveResource. The highlight was definitely Jester, a JavaScript REST implementation developed at thoughtbot. It’s modeled after ActiveResource and, boy howdy, does it look neat!
Jeremy Durham did a presentation on Memcache. Jeremy has spoken at both of the meetings I’ve attended, and on both occasions he’s provided a lot of practical, meat-and-potatos info you can use.
You can find Aron’s presentation here, and mine here.
The group is always looking for speakers, so please volunteer! If you’re in the Boston area and working with Ruby/Rails, it’s a great way to learn about the subject and to meet folks in the community.
No comments
