MongoHQ to Host with Engine Yard
Removing Stale Sessions in Heroku
Loading Session Data in Console
Textmate Footnotes with vim support
|
MongoHQ to Host with Engine YardWritten By: Jason McCay January 9th, 2010 |
We are excited to announce that as we approach the end of our beta phase, we have moved MongoHQ to the Engine Yard Cloud. Having already had great success with Engine Yard in the past, the opportunity to partner with this amazing team was welcome and exciting!
Given considerable experience managing (and worrying about) our own servers and hosting arrangements in the past, the Engine Yard Cloud has been a breath of fresh air. From worry-free uptime to painless deployment to easy of scaling to monitoring, Engine Yard really does it all. All this equates to CommonThread being able to provide a reliable product that is speedy and responsive…and that makes happy customers all around.
The response for MongoHQ during the beta release has been (literally) overwhelming. The CommonThread team is planning for 2010 to be a banner year for MongoHQ and with our cloud infrastructure in place, our commitment to expanding our services on the Amazon EC2 platform and with the Engine Yard team behind us, we are confident that our growth will be stable and sure-footed.
Finally, we want to offer special thanks for the help Ezra Zygmuntowicz provided during the transition. As a leader at Engine Yard, he is committed to helping others succeed and has contributed in numerous ways to the open-source community. He has our utmost respect.
Stay tuned for more exciting news from MongoHQ!
The CommonThread Team
About MongoHQ
MongoHQ is a cloud-based hosted database solution that allows you to quickly and easily create and interact with MongoDB instances. MongoDB is a scalable, high-performance, open-source, schema-free, document-oriented database platform that utilizes the simplicity and power of JSON-like data schemes.
Media Contact:
Jason McCay, CommonThread
jason@commonthread.com
(205) 999-5331
About Engine Yard
Engine Yard provides automation technologies and services for Ruby on Rails, including Engine Yard Cloud, an application services platform for web developers and web teams. It provides easy-to-use, automated Rails application deployment and management, with a design philosophy that allows easy migration of existing applications. Engine Yard employs top industry experts and sponsors or contributes to many Open Source projects and efforts such as Ruby on Rails (www.rubyonrails.org), JRuby (www.jruby.org) and Rubinius (www.rubini.us). Headquartered in San Francisco, Calif., Engine Yard is backed by Benchmark Capital, New Enterprise Associates, and Amazon.com. Visit www.engineyard.com.
|
Shifting our Work EnvironmentWritten By: Jason McCay June 26th, 2009 |
Recently, we decided to make a change to our primary office location and moved from our home at Innovation Depot to a new space at Shift Workspace. While we certainly enjoyed our time at Innovation Depot, there were a few specific reasons why we felt that we needed to make this change.
Ultimately, when we formed CommonThread, our goal was to have a company that was visible, active and took part in the local technology community. The open-door policy and transient nature of Shift Workspace allows for that to happen. We can easily invite people to drop by and work with us and more importantly, can work downstairs with some of the most talented freelancers in the Birmingham area. Having our company behind locked doors and security made us less accessible.
We love the idea of co-working and while we admit that the suburban-flight that occurs each day makes Birmingham not one of the more attractive places for co-working to flourish, we had a strong desire to be on the forefront of this new way of working. Other cities (Austin, San Francisco, New York, Philadelphia and Chicago) have had great success with this concept and with areas like Homewood, Bluff Park, Cahaba Heights and Highlands filled with young professionals, the opportunity is certainly there.
So, CommonThread wanted to be in a place where we could help fund this initiative and see it grow in Birmingham.
As the day goes on, many in the Birmingham technology community are finding a myriad of ways to connect with each other through social media and local user groups, but are rarely connecting in person to work together, share knowledge and expand their expertise. This is disappointing because most of these individuals sit just a couple of miles apart each day. Why not take a couple of days out of a week and work together? There is a completely separate blog post coming on this topic alone.
The beauty of the Shift Workspace arrangement is that the space for daily use is located downstairs while permanent companies have dedicated space upstairs. Since the upstairs layout is open, a community of small companies is created, allowing for people with different expertise to work together, share knowledge and help grow each other. The result is an environment that promotes new ideas over stagnation and assists small companies that do not contain within them, alone, the differing focuses of larger organizations.
Overall, Shift Workspace feels more like the home that CommonThread hoped for when we first dreamed up our company. Having the opportunity to connect with Drew Jones (who is co-author on a book about co-working in the United States) on this amazing new Birmingham work concept was something that we felt we could not pass up. We desire to see this project succeed and with a bit of effort, we think it will. I plan to write some additional articles covering more in-depth topics referencing our commitment to this way of work in the coming weeks and months.
Come hang with us one day. We would love to talk to you.
|
Removing Stale Sessions in HerokuWritten By: Ben Wyrosdick May 11th, 2009 |
Removing stale session in any app is necessary to keep a clean and happy DB. With Heroku apps it is even more important since you don’t want to pay more for a bloated DB with stale data. Heroku makes it easy to run cron tasks by calling ‘rake cron’ against your app every hour. for more info on Heroku cron support see their docs page.
To setup your cron job on Heroku create the file lib/tasks/cron.rake and place the following code in your file:
task :cron => :environment do
puts "Removing stale sessions ..."
session_count = CGI::Session::ActiveRecordStore::Session.delete_all(['updated_at < ?', 1.hour.ago])
puts "#{session_count} sessions removed"
puts "done."
end
|
Loading Session Data in ConsoleWritten By: Ben Wyrosdick February 10th, 2009 |
If you need to get data out of the session into an object in console you can use the session object to inspect it. This example assumes you are using ActiveRecord as your session store.
CGI::Session::ActiveRecordStore::Session.find_by_session_id("some_session_id").data
you can find this session_id, for example, in the production.log file on each request.
|
Textmate Footnotes with vim supportWritten By: Ben Wyrosdick June 11th, 2008 |
I just switched to doing rails development in vim rather than textmate but I sure did miss my textmate footnotes. I found a post about a plugin called redit that converted stacktraces over to links that would open in vim (textmate footnotes style) so I decided to take that and patch Textmate Footnotes. I had to make sure not to messup any of the developers who were going to still use Textmate so it patches it to do both based on an env variable we will talk about later.
First I took the controller from the afore mentioned plugin and tweaked it to make sure we were running in development mode before executing code on the server and changed it to use MacVim as the vim app. Simply create a new controller called ReditController and paste the code below changing the system call if you use something other than MacVim.
require 'base64'
class ReditController < ApplicationController
def open
if ENV['RAILS_ENV'] == 'development'
file = Base64.decode64(params[:id])
line = params[:line].to_s
# Run editor here
Thread.new do
### MacVim
# Open file in new tab of vim server
system("mvim","--remote-tab","+#{line}",file)
end
end
redirect_to :back
end
end
Next you need to replace the lib/textmate_footnotes.rb with this one. I am working with an older version of textmate footnotes so be forewarned that my file may not work 100% with your version … I will update to the latest soon and update my file. Here is an example of how the patch changes the urls generated:
def controller_url
if ENV['FOOTNOTE_APP'] == 'vim'
escape(
"/redit/open/" +
CGI.escape(Base64.encode64(controller_filename)) +
(index_of_method ? "&line=#{controller_line_number + 1}&column=3" : "")
)
else
escape(
textmate_prefix +
controller_filename +
(index_of_method ? "&line=#{controller_line_number + 1}&column=3" : "")
)
end
end
And lastly to make the plugin give you vim links rather than textmate links you need to set the FOOTNOTE_APP env variable. To make this happen every time you login place the following snippet in your ~/.bash_profile
export FOOTNOTE_APP=vim
|
Twitter HackingWritten By: Ben Wyrosdick June 5th, 2008 |
I got overloaded with work the other night so I decided to take a break from it and hack out something fairly useless but fun. I landed on a twitter bot that updates a few times daily with weather updates for my area or others I might care about. Right now I only have a Birmingham Weather and a Montgomery Weather.
The code requires 2 gems twitter & yahoo-weather. you can install them both with:
sudo gem install yahoo-weather twitter --no-ri --no-rdoc
Then the code was very simple for querying and updating:
#! /usr/bin/env ruby
require 'rubygems'
require 'yahoo-weather'
require 'twitter'
client = YahooWeather::Client.new
cities = [['35212', 'wxbhm'], ['36108', 'wxmgm']]
cities.each do |city|
response = client.lookup_location(city[0])
forecast = "Today's weather: #{response.forecasts.first.text}, Hi: #{response.forecasts.first.high}F, Lo: #{response.forecasts.first.low}F (Currently #{response.condition.text}, #{response.condition.temp}F)"
Twitter::Base.new(city[1], 'SUPER_SECRET').update(forecast)
end
Then to make it happen automagically, welcome cron:
00 13 * * * /home/deploy/twitter_wx/update_wx.rb 45 21 * * * /home/deploy/twitter_wx/update_wx.rb
It updates at 8:00am & 4:45pm. I had to put the dates in UTC and take into consideration that I am Central Timezone and add 5 hours to the time for now … if someone knows a better way to handle this in cron please let me know.
|
Phusion PassengerWritten By: Ben Wyrosdick June 2nd, 2008 |
We have been testing out mod_rails Phusion Passenger for a few weeks now on our staging server and one production server that hosts our company website and blog. Today we finally got our hands on the Ruby Enterprise Edition early release, so we are now running the full enterprise passenger stack and I must say that I am loving not having to deal with so many deploy issues like configuring monit, nginx & mongrel_cluster configs for every new app and for almost any configuration change, which we find almost unnecessary now since passenger is handling how many app instances to spawn up and it keeps an eye on instances that crash or get hosed for some reason.
We are able to able to really make better use of our VPS slices with the memory reduction we get from running passenger VS nginx+mongrel.
checkout this screencast or head over to the Phusion Passenger website to try it out for yourself.
|
Slicehost API Saves The DayWritten By: Ben Wyrosdick May 20th, 2008 |
Thanks to slicehost for giving me an API for managing my DNS zones and records via ActiveResource becauase it saved me lots of time and tedious work. I needed to update my TTL settings in all my domains and rather than having to edit all 61 entries I simply made a ruby script to do it for me:
require 'rubygems'
require 'activeresource'
API_PASSWORD = "MY_SECRET_PASSWORD"
DEFAULT_TTL = 86400
class Record < ActiveResource::Base
self.site = "https://#{API_PASSWORD}@api.slicehost.com/"
end
records = Record.find(:all)
for record in records
record.ttl = DEFAULT_TTL
record.save
end
and while we are at it lets output all of our info:
require 'rubygems'
require 'activeresource'
API_PASSWORD = "MY_SECRET_PASSWORD"
class Zone < ActiveResource::Base
self.site = "https://#{API_PASSWORD}@api.slicehost.com/"
end
class Record < ActiveResource::Base
self.site = "https://#{API_PASSWORD}@api.slicehost.com/"
end
zones = Zone.find(:all)
records = Record.find(:all)
for zone in zones
puts "zone: #{zone.origin}"
for record in records.find_all{|record| record.zone_id == zone.id}
puts " #{record.record_type}: #{record.name} - #{record.data}"
end
end
There, that was easy.
|
Running and "The Zone"Written By: Jason McCay April 26th, 2008 |
With any team, while your differences bring true creativity and problem-solving, it is good to have things in common as well. For CommonThread, one of the passions that we all share is participation in triathlons. Of course, triathlons take training and preparation, which brings me to an observation I had the other day while on one of my long runs (as I prepare for the Florida Ironman 70.3 in May).
In quite consistent fashion, I have noticed that it takes a solid 2-3 miles of running to get my body in “the zone” for going long distances. Up to that point, it seems like a fight to maintain pace and maintain determination for what I am trying to accomplish. In simple terms, I have to force myself to get to that point without stopping…what I refer to as “climbing the hill”. I have heard others describe it as a wall, but I see it much more as a steady climb that finally arrives at a place of better performance.
Similar to running, I think that getting into “the zone” when developing is not some mystical happenstance. I think it requires good planning and a solid effort to maintain focus when there is such a strong desire to occupy yourself with non-important tasks, such as: checking email, twittering, reading blogs, checking the web, etc. While there is time for that, it is those activities that seem quite beneficial when you are making the effort to get to that place of happy, effortless development.
As I noted above, the most important thing is to take the time to lay out something you want to accomplish and place it in a format that you can look upon often. This will always give you an answer to that question of “Hmm…what should I be doing.” Secondly, make a conscientious effort to turn off distractions for a while. Pick out some good music that doesn’t require your attention at the end of each song, close down twitter and email, and begin the process of climbing the hill. It takes effort on your part to get there and your initial desires will be to break out and look at irrelevant information. But, after 5-10 minutes of effort to maintain focus, the zone will begin to establish itself and you will find yourself immersed in what you need to get done.
The zone, while it sounds completely cliche´, is really where some of your best work emerges. Superficial work that you complete while stretched thin in a world of constant interruptions, is generally average and will require additional attention in the future. The zone is important…climb the hill…make the effort to get there.
|
Cherry-Pickin' in GitWritten By: Ben Wyrosdick April 19th, 2008 |
if you are trying to update to a specific commit of a git repository and can’t seem to get git pull to allow you pull that specific commit, that is because it doesn’t work that way. so you type git to see what command are available but it only shows you these common commands none of which are useful for this:
usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS] The most commonly used git commands are: add Add file contents to the index bisect Find the change that introduced a bug by binary search branch List, create, or delete branches checkout Checkout and switch to a branch clone Clone a repository into a new directory commit Record changes to the repository diff Show changes between commits, commit and working tree, etc fetch Download objects and refs from another repository grep Print lines matching a pattern init Create an empty git repository or reinitialize an existing one log Show commit logs merge Join two or more development histories together mv Move or rename a file, a directory, or a symlink pull Fetch from and merge with another repository or a local branch push Update remote refs along with associated objects rebase Forward-port local commits to the updated upstream head reset Reset current HEAD to the specified state rm Remove files from the working tree and from the index show Show various types of objects status Show the working tree status tag Create, list, delete or verify a tag object signed with GPG
What you need is git cherry-pick which allows you to update to a specific commit.
usage: git-cherry-pick [options] <commit-ish>
-n, --no-commit don't automatically commit
-e, --edit edit the commit message
-x append commit name when cherry-picking
-r no-op (backward compatibility)
-m, --mainline <n> parent number
git cherry-pick will do a fetch and merge to any commit object and then do an auto commit for you. It will automatically use the commit message of that the select commit object. IF you wish to use a different message use the -e option.
|
Complex Forms ... Just EasierWritten By: Ben Wyrosdick April 17th, 2008 |
I love having the ability to easily create/update multiple objects with a single form. There are some nice railscasts by Ryan Bates that describe how to do this in Ruby on Rails. What I needed was a way to make writing the attribute accessor methods easier. I also decided that there just weren’t enough rails plugins out there … so off to kill two birds with one stone.
The plugin is called association-attributes and it can be found on github. The goal was to make the process more semantic and most of all DRY. I decided that since we already had to have a method on the model to handle the association we would pattern after that. So, the two methods available are has_one_attr & has_many_attr.
So for a practical example of what this looks like in your model we will use a persons contact info. We also have a plugin out there that makes contact info easier since that is such a standard need and there is no reason to rewrite that all the time.
class Person < ActiveRecord::Base has_one :address, :as => :addressable, :dependent => :destroy has_one_attr :address has_many :phone_numbers, :as => :phoneable, :dependent => :destroy has_many_attr :phone_numbers end
What that does is creates the methods address_attributes & phone_number_attributes on Person so that we can use them in our form. These newly created methods handle creating & updating existing entries for addresses and phone numbers.
We use HAML for all of our views so these examples are no exception.
- fields_for("person[phone_numbers_attributes][]", @person.phone_numbers.new) do |phf|
%label{:for => "number"} Phone Number:
= phf.hidden_field :id
= phf.text_field :number
A few things to note from this example are:
fields_for has an extra [] on the first parameter … this is because we have a has_many and that tells the browser to treat that as part of an array so that we can have more than one of that same name and it will get put into the array.@person.phone_numbers.new with a variable of the actual phone number.
- fields_for("person[address_attributes]", @person.build_address) do |af|
%p
%label{:for => "line_1"} Street Address:
= af.text_field :line_1
%p
%label{:for => "city"} City:
= af.text_field :city
%p
%label{:for => "state"} State:
= af.select :state, Address::VALID_STATES.map{|s| [s,s]}.sort
%p
%label{:for => "zip"} Zip:
= af.text_field :zip
In future versions I will have a helper method that writes the fields_for for you as well. Looping through current objects and having an option to put a blank one at the end.
The result of this is that now when you submit a form to create or update a person that has these subforms using fields_for then the appropriate phone number and address objects will get created or updated as well. No more having to create the person first then associate the extra objects later. Even in the case of a has_many where the object is new it will create the object for you then create all the association objects next.
|
Jason Presents HAML to BarcampWritten By: Ben Wyrosdick April 15th, 2008 |
At BarCampBirmingham2 Jason made a presentation on HAML & SASS.
You can view the slides here on slideshare.net
|
Setting Up a Git ServerWritten By: Ben Wyrosdick April 13th, 2008 |
Setting up a remote git server is as easy as setting up a new user. In fact if you have git installed on the machine that is about all you need to do. We will not discuss setting up git … just how to set it up to be used as a remote repository.
First we need to setup a user with a home folder. We will store all the repositories in this users home folder.
sudo adduser git
Rather than giving out the password to the git user account use ssh keys to login so that you can have multiple developers connect securely and easily.
Next we will make a repository. For this example we will work with a repository called example. Login as the user git and add the repository.
# login to remote server ssh git@REMOTE_SERVER # once logged in mkdir example.git cd example.git git --bare init
That’s all there is to creating a repository. Notice we named our folder with a .git extension.
Also notice the ‘bare’ option. By default the git repository assumes that you’ll be using it as your working directory, so git stores the actual bare repository files in a .git directory alongside all the project files. Since we are setting up a remote server we don’t need copies of the files on the filesystem. Instead, all we need are the deltas and binary objects of the repository. By setting ‘bare’ we tell git not to store the current files of the repository only the diffs. This is optional as you may have need to be able to browse the files on your remote server.
Finally all you need to do is add your files to the remote repository. We will assume you don’t have any files yet.
mkdir example cd example git init touch README git add README git commit -m 'first commit' git remote add origin git@REMOTE_SERVER:example.git git push origin master
replace REMOTE_SERVER with your server name or IP
|
Bring It OnWritten By: Ben Wyrosdick February 28th, 2008 |
It’s fun to dish out criticism but it’s a bitter pill to swallow when it comes back at you. Anthony said that he was most impressed by Dr. Nic’s ability to take criticism for one of his latest projects and use that to improve his product rather than tell everyone they were wrong or just didn’t get it. The truth is that there is always someone out there with a better way to do something, and by listening to your critics you just may stumble upon the solution you were actually looking for all along.
|
Tip: Rails Default Data MigrationsWritten By: Anthony Crumley February 24th, 2008 |
Data migrations for default values can be messy. When creating default data, migrations can get lengthy and cluttered with…well…data. Down the road they can cause problems when the model they depend on has been removed.
The clutter issue can be resolved with Fixtures.create_fixtures and a YAML file containing the default data. The deleted model issue can be resolved by defining the model in the migration (Rails Recipes #30).
Example:
require "active_record/fixtures"
class CreateCategoryData < ActiveRecord::Migration
class Category < ActiveRecord::Base; end
def self.up
Fixtures.create_fixtures(
"db/fixtures",
"categories",
:categories => "CreateCategoryData::Category"
)
end
def self.down
Category.delete_all
end
end
Correction: I left off the class_names hash from create_fixtures. This parameter causes Fixtures to use the locally scoped model rather than the global one, e.g. CreateCategoryData::Category rather than Category. (2/25/2008)